floyd-warshall.js 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. var _ = require('../lodash')
  2. module.exports = floydWarshall
  3. var DEFAULT_WEIGHT_FUNC = _.constant(1)
  4. function floydWarshall (g, weightFn, edgeFn) {
  5. return runFloydWarshall(g,
  6. weightFn || DEFAULT_WEIGHT_FUNC,
  7. edgeFn || function (v) { return g.outEdges(v) })
  8. }
  9. function runFloydWarshall (g, weightFn, edgeFn) {
  10. const results = {}
  11. const nodes = g.nodes()
  12. nodes.forEach(function (v) {
  13. results[v] = {}
  14. results[v][v] = { distance: 0 }
  15. nodes.forEach(function (w) {
  16. if (v !== w) {
  17. results[v][w] = { distance: Number.POSITIVE_INFINITY }
  18. }
  19. })
  20. edgeFn(v).forEach(function (edge) {
  21. const w = edge.v === v ? edge.w : edge.v
  22. const d = weightFn(edge)
  23. results[v][w] = { distance: d, predecessor: v }
  24. })
  25. })
  26. nodes.forEach(function (k) {
  27. var rowK = results[k]
  28. nodes.forEach(function (i) {
  29. var rowI = results[i]
  30. nodes.forEach(function (j) {
  31. var ik = rowI[k]
  32. var kj = rowK[j]
  33. var ij = rowI[j]
  34. var altDistance = ik.distance + kj.distance
  35. if (altDistance < ij.distance) {
  36. ij.distance = altDistance
  37. ij.predecessor = kj.predecessor
  38. }
  39. })
  40. })
  41. })
  42. return results
  43. }