| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 |
- import _ from 'lodash'
- /*
- * A function that takes a layering (an array of layers, each with an array of
- * ordererd nodes) and a graph and returns a weighted crossing count.
- *
- * Pre-conditions:
- *
- * 1. Input graph must be simple (not a multigraph), directed, and include
- * only simple edges.
- * 2. Edges in the input graph must have assigned weights.
- *
- * Post-conditions:
- *
- * 1. The graph and layering matrix are left unchanged.
- *
- * This algorithm is derived from Barth, et al., "Bilayer Cross Counting."
- */
- function crossCount (g, layering) {
- let cc = 0
- for (let i = 1; i < layering.length; ++i) {
- cc += twoLayerCrossCount(g, layering[i - 1], layering[i])
- }
- return cc
- }
- function twoLayerCrossCount (g, northLayer, southLayer) {
- // Sort all of the edges between the north and south layers by their position
- // in the north layer and then the south. Map these edges to the position of
- // their head in the south layer.
- const southPos = _.zipObject(southLayer,
- _.map(southLayer, function (v, i) { return i }))
- const southEntries = _.flatten(_.map(northLayer, function (v) {
- return _.chain(g.outEdges(v))
- .map(function (e) {
- return { pos: southPos[e.w], weight: g.edge(e).weight }
- })
- .sortBy('pos')
- .value()
- }), true)
- // Build the accumulator tree
- let firstIndex = 1
- while (firstIndex < southLayer.length) {
- firstIndex <<= 1
- }
- const treeSize = 2 * firstIndex - 1
- firstIndex -= 1
- const tree = _.map(new Array(treeSize), function () { return 0 })
- // Calculate the weighted crossings
- let cc = 0
- _.forEach(southEntries.forEach(function (entry) {
- let index = entry.pos + firstIndex
- tree[index] += entry.weight
- let weightSum = 0
- while (index > 0) {
- if (index % 2) {
- weightSum += tree[index + 1]
- }
- index = (index - 1) >> 1
- tree[index] += entry.weight
- }
- cc += entry.weight * weightSum
- }))
- return cc
- }
- export default crossCount
|