From f24d6f10ac5151fd31943290b876750baa67b145 Mon Sep 17 00:00:00 2001 From: "Selby, Nicholas Stearns" <nselby3@gatech.edu> Date: Wed, 1 Nov 2017 16:13:59 -0400 Subject: [PATCH] Dijkstra --- sim/graph.js | 144 ++++++++++++++++++++++++++++++++++++++++++++ sim/index.html | 1 + sim/manager_nick.js | 86 ++++++++++++++++++++++++++ sim/sim_nick.js | 55 +++++++++++++++++ 4 files changed, 286 insertions(+) create mode 100644 sim/graph.js create mode 100644 sim/manager_nick.js create mode 100644 sim/sim_nick.js diff --git a/sim/graph.js b/sim/graph.js new file mode 100644 index 0000000..22111e6 --- /dev/null +++ b/sim/graph.js @@ -0,0 +1,144 @@ +var Graph = (function (undefined) { + + var extractKeys = function (obj) { + var keys = [], key; + for (key in obj) { + Object.prototype.hasOwnProperty.call(obj,key) && keys.push(key); + } + return keys; + } + + var sorter = function (a, b) { + return parseFloat (a) - parseFloat (b); + } + + var findPaths = function (map, start, end, infinity) { + infinity = infinity || Infinity; + + var costs = {}, + open = {'0': [start]}, + predecessors = {}, + keys; + + var addToOpen = function (cost, vertex) { + var key = "" + cost; + if (!open[key]) open[key] = []; + open[key].push(vertex); + } + + costs[start] = 0; + + while (open) { + if(!(keys = extractKeys(open)).length) break; + + keys.sort(sorter); + + var key = keys[0], + bucket = open[key], + node = bucket.shift(), + currentCost = parseFloat(key), + adjacentNodes = map[node] || {}; + + if (!bucket.length) delete open[key]; + + for (var vertex in adjacentNodes) { + if (Object.prototype.hasOwnProperty.call(adjacentNodes, vertex)) { + var cost = adjacentNodes[vertex], + totalCost = cost + currentCost, + vertexCost = costs[vertex]; + + if ((vertexCost === undefined) || (vertexCost > totalCost)) { + costs[vertex] = totalCost; + addToOpen(totalCost, vertex); + predecessors[vertex] = node; + } + } + } + } + + if (costs[end] === undefined) { + return null; + } else { + return predecessors; + } + + } + + var extractShortest = function (predecessors, end) { + var nodes = [], + u = end; + + while (u !== undefined) { + nodes.push(u); + u = predecessors[u]; + } + + nodes.reverse(); + return nodes; + } + + var findShortestPath = function (map, nodes) { + var start = nodes.shift(), + end, + predecessors, + path = [], + shortest; + + while (nodes.length) { + end = nodes.shift(); + predecessors = findPaths(map, start, end); + + if (predecessors) { + shortest = extractShortest(predecessors, end); + if (nodes.length) { + path.push.apply(path, shortest.slice(0, -1)); + } else { + return path.concat(shortest); + } + } else { + return null; + } + + start = end; + } + } + + var toArray = function (list, offset) { + try { + return Array.prototype.slice.call(list, offset); + } catch (e) { + var a = []; + for (var i = offset || 0, l = list.length; i < l; ++i) { + a.push(list[i]); + } + return a; + } + } + + var Graph = function (map) { + this.map = map; + } + + Graph.prototype.findShortestPath = function (start, end) { + if (Object.prototype.toString.call(start) === '[object Array]') { + return findShortestPath(this.map, start); + } else if (arguments.length === 2) { + return findShortestPath(this.map, [start, end]); + } else { + return findShortestPath(this.map, toArray(arguments)); + } + } + + Graph.findShortestPath = function (map, start, end) { + if (Object.prototype.toString.call(start) === '[object Array]') { + return findShortestPath(map, start); + } else if (arguments.length === 3) { + return findShortestPath(map, [start, end]); + } else { + return findShortestPath(map, toArray(arguments, 1)); + } + } + + return Graph; + +})(); diff --git a/sim/index.html b/sim/index.html index 75f5f54..5d1d21a 100755 --- a/sim/index.html +++ b/sim/index.html @@ -63,6 +63,7 @@ <script type="text/javascript" src="d3.v3.min.js"></script> <script type="text/javascript" src="jquery.min.js"></script> <script type="text/javascript" src="require.js"></script> + <script src="graph.js"></script> <script src="goog/base.js"></script> <script> goog.require("goog.structs.PriorityQueue") diff --git a/sim/manager_nick.js b/sim/manager_nick.js new file mode 100644 index 0000000..a80623d --- /dev/null +++ b/sim/manager_nick.js @@ -0,0 +1,86 @@ +function Manager(self) { + self.manager = this; + + this.ports = []; + this.numports = 0; + var map = {0:{1:4,2:3},1:{0:4,3:1},2:{0:3,3:1},3:{1:1,2:1}}; + var graph = new Graph(map); + const HOP_COUNT = 2; + + this.setup = function(numports) { + this.numports = numports; + this.ports = new Array(numports).fill(-1); + }; + + this.connect = function(port, id) { + + if (!(port < this.numports)) { + return; + } + + if (self.id != id) { + var prevId = this.ports[port]; + if (prevId >= 0) { + self.disconnect(prevId); + } + + this.ports[port] = id; + self.connect(id); + } + }; + + this.disconnect = function(port) { + if (!(port < this.numports)) { + return; + } + + var prevId = this.ports[port]; + if (prevId >= 0) { + self.disconnect(prevId); + } + + this.ports[port] = -1; + } + + this.send = function(port, name, msg) { + if (port < this.numports && this.ports[port] >= 0) { + self.send(this.ports[port], 'message', {name: name, obj: msg}); + } + }; + + this.sendTo = function(id, msg) { + var path = graph.findShortestPath(self.id, id); + var nextNode = path[1]; + for (var p = 0; p < this.numports; p++) { + if (this.ports[p] === parseInt(nextNode)) { + this.send(p, id, msg); + return; + } + } + } + + // Flood Packet: ['F' , HOP COUNT , ORIGINAL SENDER ID , COST 1 , RECIPIENT 1 , COST 2 , RECIPIENT 2 ...] + this.flood = function() { + for (var p = 0; p < this.numports; p++) { + this.send(this.ports[p], 'F', self.id); + } + } + + this.onReceive = function(from, o) { + var port = this.ports.indexOf(from); + if (port == -1) { + return; + } + + self.log(`got message '${o.name}' on port ${port}: '${o.obj}'`); + + if (o.name != self.id) { + this.sendTo(o.name,o.obj); + } + }; + + self.on('message', this.onReceive, this); + +} + +module.exports = Manager; diff --git a/sim/sim_nick.js b/sim/sim_nick.js new file mode 100644 index 0000000..be1efd4 --- /dev/null +++ b/sim/sim_nick.js @@ -0,0 +1,55 @@ +var net = require("./network"), + manager = require('./manager'); + +const numClients = 4; +const startupDelay = 100; + +var clients = []; +for (var i = 0; i < numClients; i++) { + c = new net.Client(); + c.use(manager); + clients.push(c); +} + +clients[0].init(function() { + this.delay(startupDelay, function() { + this.manager.setup(2); + this.manager.connect(0, 1); + this.manager.connect(1, 2); + }); + + this.delay(1000, function() { + //this.manager.send(0, 'Special Delivery', 'Surprise!!!'); + this.manager.sendTo(3, 'Tell 3 I said I love her.'); + }); + +}); + +clients[1].init(function() { + this.delay(startupDelay, function() { + this.manager.setup(2); + this.manager.connect(0, 0); + this.manager.connect(1, 3); + }); +}); + +clients[2].init(function() { + this.delay(startupDelay, function() { + this.manager.setup(2); + this.manager.connect(0, 0); + this.manager.connect(1, 3); + }); +}); + +clients[3].init(function() { + this.delay(startupDelay, function() { + this.manager.setup(2); + this.manager.connect(0, 1); + this.manager.connect(1, 2); + }); +}); + +for (var i = 0; i < numClients; i++) { + net.add(1, clients[i]); +} +net.run(100 * 1000); // runs for 100 seconds \ No newline at end of file -- GitLab