lib/get-transitive-data.js
function getClusterDissimilarity (c1: Array<Journey>, c2: Array<Journey>, {
  patterns,
  stops
}: {
  patterns: Array<Pattern>,
  stops: Array<Stop>
}): number {
  let dissimilarity = 0

  for (const j1 of c1) {
    for (const j2 of c2) {
      // if they are not the same length, don't cluster them
      if (j1.segments.length !== j2.segments.length) return Infinity

      // otherwise compute maximum dissimilarity of stops at either start or end
      for (let segment = 0; segment < j1.segments.length; segment++) {
        const s1 = j1.segments[segment]
        const s2 = j2.segments[segment]

        // if one has a walk segment where the other has a transit segment these
        // are not comparable
        if (s1.type !== s2.type) return Infinity

        // Only cluster  on the stop positions which we get from transit segments
        if (s1.type !== 'WALK') {
          dissimilarity = Math.max(
            dissimilarity,
            segmentDissimilarity(s1, s2, {patterns, stops})
          )

          // no point in continuing, these won't be merged
          if (dissimilarity > MAX_DISSIMILARITY) return Infinity
        }
      }
    }
  }

  return dissimilarity
}
function getClusterDissimilarity (c1: Array<Journey>, c2: Array<Journey>, {
  patterns,
  stops
}: {
  patterns: Array<Pattern>,
  stops: Array<Stop>
}): number {
  let dissimilarity = 0

  for (const j1 of c1) {
    for (const j2 of c2) {
      // if they are not the same length, don't cluster them
      if (j1.segments.length !== j2.segments.length) return Infinity

      // otherwise compute maximum dissimilarity of stops at either start or end
      for (let segment = 0; segment < j1.segments.length; segment++) {
        const s1 = j1.segments[segment]
        const s2 = j2.segments[segment]

        // if one has a walk segment where the other has a transit segment these
        // are not comparable
        if (s1.type !== s2.type) return Infinity

        // Only cluster  on the stop positions which we get from transit segments
        if (s1.type !== 'WALK') {
          dissimilarity = Math.max(
            dissimilarity,
            segmentDissimilarity(s1, s2, {patterns, stops})
          )

          // no point in continuing, these won't be merged
          if (dissimilarity > MAX_DISSIMILARITY) return Infinity
        }
      }
    }
  }

  return dissimilarity
}
Get the dissimilarity between two clusters, using complete linkages (see
James et al., _An Introduction to Statistical Learning, with Applications in
R_. New York: Springer, 2013, pg. 395.)