util.js 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import _ from 'lodash'
  2. /*
  3. * Initializes ranks for the input graph using the longest path algorithm. This
  4. * algorithm scales well and is fast in practice, it yields rather poor
  5. * solutions. Nodes are pushed to the lowest layer possible, leaving the bottom
  6. * ranks wide and leaving edges longer than necessary. However, due to its
  7. * speed, this algorithm is good for getting an initial ranking that can be fed
  8. * into other algorithms.
  9. *
  10. * This algorithm does not normalize layers because it will be used by other
  11. * algorithms in most cases. If using this algorithm directly, be sure to
  12. * run normalize at the end.
  13. *
  14. * Pre-conditions:
  15. *
  16. * 1. Input graph is a DAG.
  17. * 2. Input graph node labels can be assigned properties.
  18. *
  19. * Post-conditions:
  20. *
  21. * 1. Each node will be assign an (unnormalized) "rank" property.
  22. */
  23. export function longestPath (g) {
  24. const visited = {}
  25. function dfs (v) {
  26. const label = g.node(v)
  27. if (_.has(visited, v)) {
  28. return label.rank
  29. }
  30. visited[v] = true
  31. const rank = _.min(_.map(g.outEdges(v), function (e) {
  32. return dfs(e.w) - g.edge(e).minlen
  33. })) || 0
  34. return (label.rank = rank)
  35. }
  36. _.forEach(g.sources(), dfs)
  37. }
  38. /*
  39. * Returns the amount of slack for the given edge. The slack is defined as the
  40. * difference between the length of the edge and its minimum length.
  41. */
  42. export function slack (g, e) {
  43. return g.node(e.w).rank - g.node(e.v).rank - g.edge(e).minlen
  44. }
  45. export default {
  46. longestPath: longestPath,
  47. slack: slack
  48. }