| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- import _ from 'lodash'
- import { Graph } from 'graphlibrary'
- import initOrder from './init-order'
- import crossCount from './cross-count'
- import sortSubgraph from './sort-subgraph'
- import buildLayerGraph from './build-layer-graph'
- import addSubgraphConstraints from './add-subgraph-constraints'
- import util from '../util'
- /*
- * Applies heuristics to minimize edge crossings in the graph and sets the best
- * order solution as an order attribute on each node.
- *
- * Pre-conditions:
- *
- * 1. Graph must be DAG
- * 2. Graph nodes must be objects with a "rank" attribute
- * 3. Graph edges must have the "weight" attribute
- *
- * Post-conditions:
- *
- * 1. Graph nodes will have an "order" attribute based on the results of the
- * algorithm.
- */
- function order (g) {
- const maxRank = util.maxRank(g)
- const downLayerGraphs = buildLayerGraphs(g, _.range(1, maxRank + 1), 'inEdges')
- const upLayerGraphs = buildLayerGraphs(g, _.range(maxRank - 1, -1, -1), 'outEdges')
- let layering = initOrder(g)
- assignOrder(g, layering)
- let bestCC = Number.POSITIVE_INFINITY
- let best
- for (let i = 0, lastBest = 0; lastBest < 4; ++i, ++lastBest) {
- sweepLayerGraphs(i % 2 ? downLayerGraphs : upLayerGraphs, i % 4 >= 2)
- layering = util.buildLayerMatrix(g)
- const cc = crossCount(g, layering)
- if (cc < bestCC) {
- lastBest = 0
- best = _.cloneDeep(layering)
- bestCC = cc
- }
- }
- assignOrder(g, best)
- }
- function buildLayerGraphs (g, ranks, relationship) {
- return _.map(ranks, function (rank) {
- return buildLayerGraph(g, rank, relationship)
- })
- }
- function sweepLayerGraphs (layerGraphs, biasRight) {
- const cg = new Graph()
- _.forEach(layerGraphs, function (lg) {
- const root = lg.graph().root
- const sorted = sortSubgraph(lg, root, cg, biasRight)
- _.forEach(sorted.vs, function (v, i) {
- lg.node(v).order = i
- })
- addSubgraphConstraints(lg, cg, sorted.vs)
- })
- }
- function assignOrder (g, layering) {
- _.forEach(layering, function (layer) {
- _.forEach(layer, function (v, i) {
- g.node(v).order = i
- })
- })
- }
- export default order
|