From c6c9712f8231a33ccbeab75ac5c77e77bb49ce95 Mon Sep 17 00:00:00 2001 From: Lucas Dohmen Date: Mon, 9 Jul 2012 16:22:02 +0200 Subject: [PATCH] Added support for geodesics to Graph.js --- js/common/modules/graph.js | 42 +++++++ js/common/tests/shell-graph-algorithms.js | 147 +++++++++++++++++++++- 2 files changed, 186 insertions(+), 3 deletions(-) diff --git a/js/common/modules/graph.js b/js/common/modules/graph.js index d4faed0eff..7b87eacd42 100644 --- a/js/common/modules/graph.js +++ b/js/common/modules/graph.js @@ -1493,6 +1493,48 @@ Graph.prototype.size = function () { return this._edges.count(); }; +//////////////////////////////////////////////////////////////////////////////// +/// @brief return all shortest paths +/// +/// @FUN{@FA{graph}.geodesics()} +/// +//////////////////////////////////////////////////////////////////////////////// + +Graph.prototype.geodesics = function (options) { + var sources = this._vertices.toArray(), + targets = sources.slice(), + geodesics = [], + graph = this, + vertexConstructor; + + options = options || {}; + + vertexConstructor = function(raw_vertex) { + return graph.constructVertex(raw_vertex._id); + }; + + sources = sources.map(vertexConstructor); + targets = targets.map(vertexConstructor); + + sources.forEach(function(source) { + targets = targets.slice(1); + + targets.forEach(function(target) { + var pathes = source.pathTo(target); + + if (pathes.length > 0 && (!options.threshold || pathes[0].length > 2)) { + if (options.grouped) { + geodesics.push(pathes); + } else { + geodesics = geodesics.concat(pathes); + } + } + }); + }); + + return geodesics; +}; + //////////////////////////////////////////////////////////////////////////////// /// @brief calculate a measurement /// diff --git a/js/common/tests/shell-graph-algorithms.js b/js/common/tests/shell-graph-algorithms.js index 274e45e566..793f1484a6 100644 --- a/js/common/tests/shell-graph-algorithms.js +++ b/js/common/tests/shell-graph-algorithms.js @@ -611,12 +611,153 @@ function commonSuite() { }; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief test suite: Geodesic Distances and Betweenness +//////////////////////////////////////////////////////////////////////////////// + +function geodesicSuite() { + var Graph = require("graph").Graph, + graph_name = "UnitTestsCollectionGraph", + vertex = "UnitTestsCollectionVertex", + edge = "UnitTestsCollectionEdge", + graph = null; + + return { + +//////////////////////////////////////////////////////////////////////////////// +/// @brief set up +//////////////////////////////////////////////////////////////////////////////// + + setUp : function () { + try { + try { + // Drop the graph if it exsits + graph = new Graph(graph_name); + print("FOUND: "); + PRINT_OBJECT(graph); + graph.drop(); + } catch (err1) { + } + + graph = new Graph(graph_name, vertex, edge); + } catch (err2) { + console.error("[FAILED] setup failed:" + err2); + } + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief tear down +//////////////////////////////////////////////////////////////////////////////// + + tearDown : function () { + try { + if (graph !== null) { + graph.drop(); + } + } catch (err) { + console.error("[FAILED] tear-down failed:" + err); + } + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief Test Geodesics +//////////////////////////////////////////////////////////////////////////////// + + testGeodesics: function () { + var v1 = graph.addVertex(1), + v2 = graph.addVertex(2), + v3 = graph.addVertex(3), + v4 = graph.addVertex(4), + v5 = graph.addVertex(5), + geodesics; + + graph.addEdge(v1, v2); + graph.addEdge(v2, v3); + graph.addEdge(v2, v4); + graph.addEdge(v3, v4); + graph.addEdge(v3, v5); + graph.addEdge(v4, v5); + + geodesics = graph.geodesics().map(function(geodesic) { + return geodesic.length; + }); + geodesics.sort(); + + assertEqual(geodesics.length, 12); + assertEqual(geodesics.indexOf(2), 0); + assertEqual(geodesics.indexOf(3), 6); + assertEqual(geodesics.indexOf(4), 10); + assertEqual(geodesics[11], 4); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief Test Grouped Geodesics +//////////////////////////////////////////////////////////////////////////////// + + testGroupedGeodesics: function () { + var v1 = graph.addVertex(1), + v2 = graph.addVertex(2), + v3 = graph.addVertex(3), + v4 = graph.addVertex(4), + v5 = graph.addVertex(5), + geodesics; + + graph.addEdge(v1, v2); + graph.addEdge(v2, v3); + graph.addEdge(v2, v4); + graph.addEdge(v3, v4); + graph.addEdge(v3, v5); + graph.addEdge(v4, v5); + + geodesics = graph.geodesics({ grouped: true }).map(function(geodesic) { + return geodesic.length; + }); + geodesics.sort(); + + assertEqual(geodesics.length, 10); + assertEqual(geodesics.indexOf(1), 0); + assertEqual(geodesics.indexOf(2), 8); + assertEqual(geodesics[9], 2); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief Test Grouped Geodesics with Threshold +//////////////////////////////////////////////////////////////////////////////// + + testGroupedGeodesicsWithThreshold: function () { + var v1 = graph.addVertex(1), + v2 = graph.addVertex(2), + v3 = graph.addVertex(3), + v4 = graph.addVertex(4), + v5 = graph.addVertex(5), + options, + geodesics; + + graph.addEdge(v1, v2); + graph.addEdge(v2, v3); + graph.addEdge(v2, v4); + graph.addEdge(v3, v4); + graph.addEdge(v3, v5); + graph.addEdge(v4, v5); + + options = { grouped: true, threshold: true }; + geodesics = graph.geodesics(options).sort(); + + assertEqual(geodesics.length, 4); + }, + + + + }; +} + //////////////////////////////////////////////////////////////////////////////// /// @brief executes the test suites //////////////////////////////////////////////////////////////////////////////// -jsunity.run(neighborSuite); -jsunity.run(dijkstraSuite); -jsunity.run(commonSuite); +//jsunity.run(neighborSuite); +//jsunity.run(dijkstraSuite); +//jsunity.run(commonSuite); +jsunity.run(geodesicSuite); return jsunity.done();