index.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import _ from 'lodash'
  2. import { Graph } from 'graphlibrary'
  3. import initOrder from './init-order'
  4. import crossCount from './cross-count'
  5. import sortSubgraph from './sort-subgraph'
  6. import buildLayerGraph from './build-layer-graph'
  7. import addSubgraphConstraints from './add-subgraph-constraints'
  8. import util from '../util'
  9. /*
  10. * Applies heuristics to minimize edge crossings in the graph and sets the best
  11. * order solution as an order attribute on each node.
  12. *
  13. * Pre-conditions:
  14. *
  15. * 1. Graph must be DAG
  16. * 2. Graph nodes must be objects with a "rank" attribute
  17. * 3. Graph edges must have the "weight" attribute
  18. *
  19. * Post-conditions:
  20. *
  21. * 1. Graph nodes will have an "order" attribute based on the results of the
  22. * algorithm.
  23. */
  24. function order (g) {
  25. const maxRank = util.maxRank(g)
  26. const downLayerGraphs = buildLayerGraphs(g, _.range(1, maxRank + 1), 'inEdges')
  27. const upLayerGraphs = buildLayerGraphs(g, _.range(maxRank - 1, -1, -1), 'outEdges')
  28. let layering = initOrder(g)
  29. assignOrder(g, layering)
  30. let bestCC = Number.POSITIVE_INFINITY
  31. let best
  32. for (let i = 0, lastBest = 0; lastBest < 4; ++i, ++lastBest) {
  33. sweepLayerGraphs(i % 2 ? downLayerGraphs : upLayerGraphs, i % 4 >= 2)
  34. layering = util.buildLayerMatrix(g)
  35. const cc = crossCount(g, layering)
  36. if (cc < bestCC) {
  37. lastBest = 0
  38. best = _.cloneDeep(layering)
  39. bestCC = cc
  40. }
  41. }
  42. assignOrder(g, best)
  43. }
  44. function buildLayerGraphs (g, ranks, relationship) {
  45. return _.map(ranks, function (rank) {
  46. return buildLayerGraph(g, rank, relationship)
  47. })
  48. }
  49. function sweepLayerGraphs (layerGraphs, biasRight) {
  50. const cg = new Graph()
  51. _.forEach(layerGraphs, function (lg) {
  52. const root = lg.graph().root
  53. const sorted = sortSubgraph(lg, root, cg, biasRight)
  54. _.forEach(sorted.vs, function (v, i) {
  55. lg.node(v).order = i
  56. })
  57. addSubgraphConstraints(lg, cg, sorted.vs)
  58. })
  59. }
  60. function assignOrder (g, layering) {
  61. _.forEach(layering, function (layer) {
  62. _.forEach(layer, function (v, i) {
  63. g.node(v).order = i
  64. })
  65. })
  66. }
  67. export default order