From 3673b229dd8dfc7c8019c96a8df9c7a5e190d435 Mon Sep 17 00:00:00 2001 From: Waldemar Bira Date: Thu, 18 Oct 2018 23:05:58 +0200 Subject: [PATCH] Implemented Bellman-Ford algorithm --- src/algorithms/graph/bellman-ford.js | 48 ++++++++++++++++++++++++ src/algorithms/graph/index.js | 5 +++ src/algorithms/index.js | 2 + test/algorithms/graph/testBellmanFord.js | 30 +++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 src/algorithms/graph/bellman-ford.js create mode 100644 src/algorithms/graph/index.js create mode 100644 test/algorithms/graph/testBellmanFord.js diff --git a/src/algorithms/graph/bellman-ford.js b/src/algorithms/graph/bellman-ford.js new file mode 100644 index 00000000..a1211fdf --- /dev/null +++ b/src/algorithms/graph/bellman-ford.js @@ -0,0 +1,48 @@ + +const getAllEdges = (G) => { + const edges = []; + G.vertices.forEach((vertex) => { + const neighbours = G.getNeighbours(vertex); + if (neighbours && neighbours.length) { + neighbours.forEach((n) => { + edges.push({ + from: vertex, + to: n, + weight: G.getEdgeWeight(vertex, n) + }); + }); + } + }); + return edges; +}; + +/** + * Calculates GCD of two numbers + * @param {Graph} G weighted digraph (with positive or negative weights on edges) + * withouth negative cycles (vertices should have names starting from 0, 1, 2... n) + * @return {Array[Array]} shortest paths between all vertices + * + * References: https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm + */ +const bellmanford = (G, source) => { + const graphSize = G.size; + + const distance = new Array(graphSize); + for (let i = 0; i < graphSize; i += 1) { + distance[i] = Infinity; + } + distance[source] = 0; + + const edges = getAllEdges(G); + for (let i = 0; i < graphSize - 1; i += 1) { + edges.forEach(({ from, to, weight }) => { + if (distance[from] + weight < distance[to]) { + distance[to] = distance[from] + weight; + } + }); + } + return distance; +}; + + +module.exports = bellmanford; diff --git a/src/algorithms/graph/index.js b/src/algorithms/graph/index.js new file mode 100644 index 00000000..34530aa0 --- /dev/null +++ b/src/algorithms/graph/index.js @@ -0,0 +1,5 @@ +const bellmanford = require('./bellman-ford'); + +module.exports = { + bellmanford +}; diff --git a/src/algorithms/index.js b/src/algorithms/index.js index 2335cebb..d6056525 100644 --- a/src/algorithms/index.js +++ b/src/algorithms/index.js @@ -1,10 +1,12 @@ const geometry = require('./geometry'); +const graph = require('./graph'); const math = require('./math'); const string = require('./string'); const search = require('./search'); const sort = require('./sort'); module.exports = { + graph, geometry, math, string, diff --git a/test/algorithms/graph/testBellmanFord.js b/test/algorithms/graph/testBellmanFord.js new file mode 100644 index 00000000..950cc66a --- /dev/null +++ b/test/algorithms/graph/testBellmanFord.js @@ -0,0 +1,30 @@ +/* eslint-env mocha */ +const bellmanford = require('../../../src').algorithms.graph.bellmanford; +const Graph = require('../../../src').datastructures.Graph; +const assert = require('assert'); + +describe('Bellman-Ford', () => { + it('should return correct shortest path for directed graph', () => { + const inst = new Graph(true); + inst.addVertex(0); + inst.addVertex(1); + inst.addVertex(2); + inst.addVertex(3); + inst.addVertex(4); + inst.addVertex(5); + + + inst.addEdge(0, 1, 10); + inst.addEdge(0, 5, 8); + inst.addEdge(1, 3, 2); + inst.addEdge(2, 1, 1); + inst.addEdge(3, 2, -2); + + inst.addEdge(4, 3, -1); + inst.addEdge(4, 1, -4); + inst.addEdge(5, 4, 1); + + const result = bellmanford(inst, 0); + assert.deepStrictEqual(result, [0, 5, 5, 7, 9, 8]); + }); +});