From 2af52195828f2e53fc94c4fb2160a120b585b4cd Mon Sep 17 00:00:00 2001 From: Benjamin Van Treese Date: Fri, 7 Jun 2024 15:04:52 -0500 Subject: [PATCH] feat: Add graph, node interfaces. Add BF DF iterators. --- .vim/coc-settings.json | 3 + src/dropecho/ds/BSPNode.hx | 8 +- src/dropecho/ds/Graph.hx | 201 +++++++------------- src/dropecho/ds/GraphNode.hx | 28 +-- src/dropecho/ds/IGraph.hx | 126 ++++++++++++ src/dropecho/ds/IGraphNode.hx | 40 ++++ src/dropecho/ds/Queue.hx | 8 + src/dropecho/ds/algos/InOrderTraversal.hx | 4 +- src/dropecho/ds/algos/PostOrderTraversal.hx | 4 +- src/dropecho/ds/algos/PreOrderTraversal.hx | 4 +- src/dropecho/ds/graph/BFIterator.hx | 34 ++++ src/dropecho/ds/graph/DFIterator.hx | 34 ++++ src/dropecho/ds/graph/Grammar.hx | 35 ---- src/dropecho/ds/graph/Search.hx | 18 +- src/dropecho/ds/graph/Traversal.hx | 76 -------- test/algos/InOrderTraversalTests.hx | 10 +- test/algos/PostOrderTraversalTests.hx | 10 +- test/algos/PreOrderTraversalTests.hx | 10 +- test/bsp/BSPNodeTests.hx | 2 +- test/bsp/BSPTreeTests.hx | 2 +- test/graph/BFSTests.hx | 114 ----------- test/graph/DFSTests.hx | 111 ----------- test/graph/DijkstraTests.hx | 62 +++--- test/graph/GrammarTests.hx | 36 ---- test/graph/GraphNodeTests.hx | 4 +- test/graph/GraphTests.hx | 72 +++---- test/graph/IteratorTests.hx | 79 ++++++++ 27 files changed, 509 insertions(+), 626 deletions(-) create mode 100644 .vim/coc-settings.json create mode 100644 src/dropecho/ds/IGraph.hx create mode 100644 src/dropecho/ds/IGraphNode.hx create mode 100644 src/dropecho/ds/graph/BFIterator.hx create mode 100644 src/dropecho/ds/graph/DFIterator.hx delete mode 100644 src/dropecho/ds/graph/Grammar.hx delete mode 100644 src/dropecho/ds/graph/Traversal.hx delete mode 100644 test/graph/BFSTests.hx delete mode 100644 test/graph/DFSTests.hx delete mode 100644 test/graph/GrammarTests.hx create mode 100644 test/graph/IteratorTests.hx diff --git a/.vim/coc-settings.json b/.vim/coc-settings.json new file mode 100644 index 0000000..c0c1634 --- /dev/null +++ b/.vim/coc-settings.json @@ -0,0 +1,3 @@ +{ + "haxe.hxml": "test.hxml" +} \ No newline at end of file diff --git a/src/dropecho/ds/BSPNode.hx b/src/dropecho/ds/BSPNode.hx index b36bb28..1735f96 100644 --- a/src/dropecho/ds/BSPNode.hx +++ b/src/dropecho/ds/BSPNode.hx @@ -41,8 +41,8 @@ class BSPNode extends GraphNode { this.left = node; node.parent = this; graph.addNode(node); - graph.addUniEdge(this.id, node.id, "left"); - graph.addUniEdge(node.id, this.id, "parent"); + graph.addUniEdge(this.label, node.label, "left"); + graph.addUniEdge(node.label, this.label, "parent"); return node; } @@ -57,8 +57,8 @@ class BSPNode extends GraphNode { this.right = node; node.parent = this; graph.addNode(node); - graph.addUniEdge(this.id, node.id, "right"); - graph.addUniEdge(node.id, this.id, "parent"); + graph.addUniEdge(this.label, node.label, "right"); + graph.addUniEdge(node.label, this.label, "parent"); return node; } diff --git a/src/dropecho/ds/Graph.hx b/src/dropecho/ds/Graph.hx index 1fc56e3..9318256 100644 --- a/src/dropecho/ds/Graph.hx +++ b/src/dropecho/ds/Graph.hx @@ -1,201 +1,134 @@ package dropecho.ds; +import dropecho.ds.IGraph; import dropecho.interop.AbstractMap; -/** - * A graph data structure. - * - * Depending on methods used, can represent both a directed and non-directed graph. - * @param T - The node data type (stored within nodes). - * @param U - The edge data type (stored within edges). - */ @:nativeGen @:expose("Graph") -class Graph { +@:inheritDoc(IGraph) +class Graph implements IGraph { /** The nodes or vertices of the graph. */ - public var nodes:AbstractMap>; + public var nodes:AbstractMap>; /** The edges of the graph. */ public var edges:AbstractMap>; public function new() { - nodes = new AbstractMap>(); + nodes = new AbstractMap>(); edges = new AbstractMap>(); } - /** - * Creates a new node from a given value - * @param value The value to assign to the new node. - * @return The new node. - */ - public function createNode(value:T, ?id:String):GraphNode { - return addNode(new GraphNode(value, id)); + @:inheritDoc(IGraph.createNode) + public function createNode(value:T, ?label:String) { + return addNode(new GraphNode(value, label)); } - /** - * Add an existing node to this graph. - * This will set the internal graph property on the node to this. - * @param node The Node to add. - * @return The added graph node. - */ - public function addNode(node:GraphNode):GraphNode { + @:inheritDoc(IGraph.addNode) + public function addNode(node:IGraphNode) { node.graph = this; - return nodes.set(node.id, node); + return nodes.set(node.label, node); } - /** - * Add a unidirectional edge from node to another. - * - * @param nodeId The start node of the edge. - * @param otherId The end node of the edge. - * @param data The data to assign to the edge. - */ - public function addUniEdge(fromId:String, toId:String, ?data:U):Void { - if (!edges.exists(fromId)) { - edges.set(fromId, new AbstractMap()); + @:inheritDoc(IGraph.addUniEdge) + public function addUniEdge(fromLabel:String, toLabel:String, ?data:U):Void { + if (!edges.exists(fromLabel)) { + edges.set(fromLabel, new AbstractMap()); } - edges.get(fromId).set(toId, data); + edges.get(fromLabel).set(toLabel, data); } - /** - * Add a bidirectional edge from node to another. - * @param nodeId - One node of the edge. - * @param otherId - The other node of the edge. - * @param data - The data to assign to the edge. - */ - public function addBiEdge(nodeId:String, otherId:String, ?data:U):Void { - addUniEdge(nodeId, otherId, data); - addUniEdge(otherId, nodeId, data); + @:inheritDoc(IGraph.addBiEdge) + public function addBiEdge(nodeLabel:String, otherLabel:String, ?data:U):Void { + addUniEdge(nodeLabel, otherLabel, data); + addUniEdge(otherLabel, nodeLabel, data); } - /** - * Removes a node (and it's edges) from the graph. - * - * @param id - The id of the node to remove from the graph. - */ - public function remove(id:String):Void { - for (n in inNeighborIds(nodes.get(id))) { - edges.get(n).remove(id); + @:inheritDoc(IGraph.remove) + public function remove(label:String):Void { + for (n in inNeighborLabels(nodes.get(label))) { + edges.get(n).remove(label); } - edges.remove(id); - nodes.remove(id); + edges.remove(label); + nodes.remove(label); } - /** - * Get the in neighbors of the given node, filtering by the edge data. - * @param node - The node to find the in neighbors of. - * @param filter - The edge data filter. - * @return The list of in neighbor nodes. - */ - public function inNeighbors(node:GraphNode, ?filter:(String, U) -> Bool):Array> { - return inNeighborIds(node, filter).map(id -> nodes.get(id)); + @:inheritDoc(IGraph.remove) + public function inNeighbors(node:IGraphNode, ?filter:(String, U) -> Bool):Array> { + return inNeighborLabels(node, filter).map(label -> nodes.get(label)); } - /** - * Get the in neighbor ids of the given node, filtering by the edge data. - * @param node - The node to find the in neighbors of. - * @param filter - The edge data filter. - * @return The list of in neighbor node ids. - */ - public function inNeighborIds(node:GraphNode, ?filter:(String, U) -> Bool):Array { - var ids = []; + public function inNeighborLabels(node:IGraphNode, ?filter:(String, U) -> Bool):Array { + var labels = []; // Get all edges as id, nodeEdges pairs - for (id => nodeEdges in edges) { + for (label => nodeEdges in edges) { // If an edge exists from some other node to this node, add it to list. - if (nodeEdges.exists(node.id)) { - ids.push(id); + if (nodeEdges.exists(node.label)) { + labels.push(label); } } // TODO: Add back in filter. // if (edges.exists(node.id) && (filter == null || filter(id, edge.get(node.id)))) { - return ids; + return labels; } - /** - * Get the out-neighbors of the node. - * @param node - The node to get out-neighbors of. - * @param filter - A filter that sorts by either id or edge data. - * @return The list of out-neighbor nodes. - */ - public function outNeighbors(node:GraphNode, ?filter:(String, U) -> Bool):Array> { - return outNeighborIds(node, filter).map(id -> nodes.get(id)); + @:inheritDoc(IGraph.outNeighbors) + public function outNeighbors(node:IGraphNode, ?filter:(String, U) -> Bool):Array> { + return outNeighborLabels(node, filter).map(label -> nodes.get(label)); } - /** - * Get the out-neighbors ids of the node. - * @param node - The node to get out-neighbors of. - * @param filter - A filter that sorts by either id or edge data. - * @return The list of out-neighbor node ids. - */ - public function outNeighborIds(node:GraphNode, ?filter:(String, U) -> Bool):Array { - if (!edges.exists(node.id)) { + @:inheritDoc(IGraph.outNeighborLabels) + public function outNeighborLabels(node:IGraphNode, ?filter:(String, U) -> Bool):Array { + if (!edges.exists(node.label)) { return []; } - var ids = [ - for (id => data in edges.get(node.id)) { - if (filter == null || filter(id, data)) { - id; + var labels = [ + for (label => data in edges.get(node.label)) { + if (filter == null || filter(label, data)) { + label; } } ]; - haxe.ds.ArraySort.sort(ids, Reflect.compare); - return ids; + haxe.ds.ArraySort.sort(labels, Reflect.compare); + return labels; } - /** - * Get the in and out neighbor ids of the node. - * @param node - The node to get neighbors of. - * @param filter - A filter that sorts by either id or edge data. - * @return The list of neighbor node ids. - */ - public function neighborIds(node:GraphNode, ?filter:(String, U) -> Bool):Array { - return outNeighborIds(node, filter).concat(inNeighborIds(node, filter)); + @:inheritDoc(IGraph.neighborLabels) + public function neighborLabels(node:IGraphNode, ?filter:(String, U) -> Bool):Array { + return outNeighborLabels(node, filter).concat(inNeighborLabels(node, filter)); } - /** - * Get the in and out neighbor nodes of the node. - * @param node - The node to get neighbors of. - * @param filter - A filter that sorts by either id or edge data. - * @return The list of neighbor nodes. - */ - public function neighbors(node:GraphNode, ?filter:(String, U) -> Bool):Array> { + @:inheritDoc(IGraph.neighbors) + public function neighbors(node:IGraphNode, ?filter:(String, U) -> Bool):Array> { return outNeighbors(node, filter).concat(inNeighbors(node, filter)); } - /** - * Get the data from the edge between From and To. - * @param fromId - The start node of the edge. - * @param toId - The end node of the edge. - * @return The edge data. - */ - public function edgeData(fromId:String, toId:String):Null { - if (edges.exists(fromId)) { - var edgefrom = edges.get(fromId); - if (edgefrom.exists(toId)) { - return edgefrom.get(toId); + @:inheritDoc(IGraph.edgeData) + public function edgeData(fromLabel:String, toLabel:String):Null { + if (edges.exists(fromLabel)) { + var edgefrom = edges.get(fromLabel); + if (edgefrom.exists(toLabel)) { + return edgefrom.get(toLabel); } } return null; } - /** - * Outputs the graph as a string, represented by an adjacency list. - */ + @:inheritDoc(IGraph.toString) public function toString() { var adjList = "\nGraph:\n"; adjList += "out-Neighbors:\n"; for (node in nodes) { - adjList += node.id; + adjList += node.label; adjList += "\t-> "; var neighbors = outNeighbors(node); for (node in neighbors) { - adjList += node.id; + adjList += node.label; if (neighbors.indexOf(node) != neighbors.length - 1) { adjList += ","; } @@ -205,11 +138,11 @@ class Graph { adjList += "in-Neighbors:\n"; for (node in nodes) { - adjList += node.id; + adjList += node.label; adjList += "\t-> "; var neighbors = inNeighbors(node); for (node in neighbors) { - adjList += node.id; + adjList += node.label; if (neighbors.indexOf(node) != neighbors.length - 1) { adjList += ","; } @@ -220,20 +153,18 @@ class Graph { return adjList; } - /** - * Outputs the graph as a string in graph-viz dot format. - */ + @:inheritDoc(IGraph.toDot) public function toDot() { var dot = "digraph {\n"; for (node in nodes) { - dot += '\t${node.id}\n'; + dot += '\t${node.label}\n'; } for (node in nodes) { var neighbors = outNeighbors(node); for (n in neighbors) { - dot += '\t${node.id} -> ${n.id}\n'; + dot += '\t${node.label} -> ${n.label}\n'; } } diff --git a/src/dropecho/ds/GraphNode.hx b/src/dropecho/ds/GraphNode.hx index 1b08c89..71327e5 100644 --- a/src/dropecho/ds/GraphNode.hx +++ b/src/dropecho/ds/GraphNode.hx @@ -7,42 +7,42 @@ package dropecho.ds; */ @:expose("GraphNode") @:nativeGen -class GraphNode { - public var id:String; +class GraphNode implements IGraphNode { + public var label:String; public var value:T; public var graph:Graph; - public function new(?value:T, ?id:String) { - this.id = id != null ? id : Std.string(Std.random(10000000)); + public function new(?value:T, ?label:String) { + this.label = label != null ? label : Std.string(Std.random(10000000)); this.value = value; } /** * Add a unidirectional edge from node to another. * - * @param otherId - The end node of the edge. + * @param otherLabel - The end node of the edge. * @param data - The data to assign to the edge. */ - public function addUniEdge(to:GraphNode, ?data:U) { - graph.addUniEdge(id, to.id); + public function addUniEdge(to:IGraphNode, ?data:U) { + graph.addUniEdge(label, to.label); } /** * Add a bidirectional edge from node to another. * - * @param otherId - The end node of the edge. + * @param otherLabel - The end node of the edge. * @param data - The data to assign to the edge. */ - public function addBiEdge(to:GraphNode, ?data:U) { - graph.addBiEdge(id, to.id); + public function addBiEdge(to:IGraphNode, ?data:U) { + graph.addBiEdge(label, to.label); } /** - * Get the in and out neighbor ids of the node. - * @return The list of neighbor node ids. + * Get the in and out neighbor labels of the node. + * @return The list of neighbor node labels. */ - public function neighborIds() { - return graph.neighborIds(this); + public function neighborLabels() { + return graph.neighborLabels(this); } /** diff --git a/src/dropecho/ds/IGraph.hx b/src/dropecho/ds/IGraph.hx new file mode 100644 index 0000000..1c528b6 --- /dev/null +++ b/src/dropecho/ds/IGraph.hx @@ -0,0 +1,126 @@ +package dropecho.ds; + +import dropecho.interop.AbstractMap; + +/** + * A graph data structure. + * + * Depending on methods used, can represent both a directed and non-directed graph. + * @param T The node data type (stored within nodes). + * @param U The edge data type (stored within edges). + */ +interface IGraph { + /** The nodes or vertices of the graph. */ + public var nodes:AbstractMap>; + + /** The edges of the graph. */ + public var edges:AbstractMap>; + + /** + * Create a new node from a given value. + * + * @param value The value to assign to the new node. + * @param label The optional label to assign to the new node. + * @return The new node. + */ + public function createNode(value:T, ?label:String):IGraphNode; + + /** + * Add an existing node to this graph. + * This will set the internal graph property on the node to this. + * + * @param node The Node to add. + * @return The added graph node. + */ + public function addNode(node:GraphNode):IGraphNode; + + /** + * Add a unidirectional edge from node to another. + * + * @param fromLabel The start node of the edge. + * @param toLabel The end node of the edge. + * @param data The data to assign to the edge. + */ + public function addUniEdge(fromLabel:String, toLabel:String, ?data:U):Void; + + /** + * Add a bidirectional edge from node to another. + * @param label1 One node of the edge. + * @param label2 The other node of the edge. + * @param data The data to assign to the edge. + */ + public function addBiEdge(label1:String, label2:String, ?data:U):Void; + + /** + * Removes a node (and it's edges) from the graph. + * + * @param id The id of the node to remove from the graph. + */ + public function remove(id:String):Void; + + /** + * Get the in neighbors of the given node, filtering by the edge data. + * @param node The node to find the in neighbors of. + * @param filter The edge data filter. + * @return The list of in neighbor nodes. + */ + public function inNeighbors(node:IGraphNode, ?filter:(String, U) -> Bool):Array>; + + /** + * Get the in neighbor ids of the given node, filtering by the edge data. + * @param node The node to find the in neighbors of. + * @param filter The edge data filter. + * @return The list of in neighbor node ids. + */ + public function inNeighborLabels(node:GraphNode, ?filter:(String, U) -> Bool):Array; + + /** + * Get the out-neighbors of the node. + * @param node The node to get out-neighbors of. + * @param filter A filter that sorts by either id or edge data. + * @return The list of out-neighbor nodes. + */ + public function outNeighbors(node:IGraphNode, ?filter:(String, U) -> Bool):Array>; + + /** + * Get the out-neighbors ids of the node. + * @param node The node to get out-neighbors of. + * @param filter A filter that sorts by either id or edge data. + * @return The list of out-neighbor node ids. + */ + public function outNeighborLabels(node:IGraphNode, ?filter:(String, U) -> Bool):Array; + + /** + * Get the in and out neighbor ids of the node. + * @param node The node to get neighbors of. + * @param filter A filter that sorts by either id or edge data. + * @return The list of neighbor node ids. + */ + public function neighborLabels(node:IGraphNode, ?filter:(String, U) -> Bool):Array; + + /** + * Get the in and out neighbor nodes of the node. + * @param node - The node to get neighbors of. + * @param filter - A filter that sorts by either id or edge data. + * @return The list of neighbor nodes. + */ + public function neighbors(node:IGraphNode, ?filter:(String, U) -> Bool):Array>; + + /** + * Get the data from the edge between From and To. + * @param fromLabel The start node of the edge. + * @param toLabel The end node of the edge. + * @return The edge data. + */ + public function edgeData(fromLabel:String, toLabeloId:String):Null; + + /** + * Outputs the graph as a string, represented by an adjacency list. + */ + public function toString():String; + + /** + * Outputs the graph as a string in graph-viz dot format. + */ + public function toDot():String; +} diff --git a/src/dropecho/ds/IGraphNode.hx b/src/dropecho/ds/IGraphNode.hx new file mode 100644 index 0000000..dbdda1d --- /dev/null +++ b/src/dropecho/ds/IGraphNode.hx @@ -0,0 +1,40 @@ +package dropecho.ds; + +/** + * A graph node data structure. + * @param T The node data type (stored within nodes). + * @param U The edge data type (stored within edges). + */ +interface IGraphNode { + public var label:String; + public var value:T; + public var graph:Graph; + + /** + * Add a unidirectional edge from node to another. + * + * @param otherLabel The end node of the edge. + * @param data The data to assign to the edge. + */ + public function addUniEdge(to:GraphNode, ?data:U):Void; + + /** + * Add a bidirectional edge from node to another. + * + * @param otherLabel The end node of the edge. + * @param data The data to assign to the edge. + */ + public function addBiEdge(to:GraphNode, ?data:U):Void; + + /** + * Get the in and out neighbor labels of the node. + * @return The list of neighbor node labels. + */ + public function neighborLabels():Array; + + /** + * Get the in and out neighbor nodes of the node. + * @return The list of neighbor nodes. + */ + public function neighbors():Array>; +} diff --git a/src/dropecho/ds/Queue.hx b/src/dropecho/ds/Queue.hx index 0ec8fb8..cad5215 100644 --- a/src/dropecho/ds/Queue.hx +++ b/src/dropecho/ds/Queue.hx @@ -52,6 +52,14 @@ class Queue { _data = new haxe.ds.List(); } + inline public function push(value:T) { + _data.add(value); + } + + inline public function pop() { + return _data.pop(); + } + inline public function enqueue(value:T) { _data.add(value); } diff --git a/src/dropecho/ds/algos/InOrderTraversal.hx b/src/dropecho/ds/algos/InOrderTraversal.hx index e5faad9..c9a8290 100644 --- a/src/dropecho/ds/algos/InOrderTraversal.hx +++ b/src/dropecho/ds/algos/InOrderTraversal.hx @@ -16,12 +16,12 @@ class InOrderTraversal { if (visitor != null) { if (visitor(node)) { - visited.push(node.id); + visited.push(node.label); } else { return visited; } } else { - visited.push(node.id); + visited.push(node.label); } if (node.right != null) { diff --git a/src/dropecho/ds/algos/PostOrderTraversal.hx b/src/dropecho/ds/algos/PostOrderTraversal.hx index 25543bc..20f8479 100644 --- a/src/dropecho/ds/algos/PostOrderTraversal.hx +++ b/src/dropecho/ds/algos/PostOrderTraversal.hx @@ -19,12 +19,12 @@ class PostOrderTraversal { if (visitor != null) { if (visitor(node)) { - visited.push(node.id); + visited.push(node.label); } else { return visited; } } else { - visited.push(node.id); + visited.push(node.label); } return visited; diff --git a/src/dropecho/ds/algos/PreOrderTraversal.hx b/src/dropecho/ds/algos/PreOrderTraversal.hx index 31d2a1a..95bc4aa 100644 --- a/src/dropecho/ds/algos/PreOrderTraversal.hx +++ b/src/dropecho/ds/algos/PreOrderTraversal.hx @@ -12,12 +12,12 @@ class PreOrderTraversal { public function run(node:BSPNode, ?visitor:BSPNode->Bool) { if (visitor != null) { if (visitor(node)) { - visited.push(node.id); + visited.push(node.label); } else { return visited; } } else { - visited.push(node.id); + visited.push(node.label); } if (node.left != null) { diff --git a/src/dropecho/ds/graph/BFIterator.hx b/src/dropecho/ds/graph/BFIterator.hx new file mode 100644 index 0000000..ed8f0f2 --- /dev/null +++ b/src/dropecho/ds/graph/BFIterator.hx @@ -0,0 +1,34 @@ +package dropecho.ds.graph; + +import dropecho.ds.IGraphNode; + +class BFIterator { + var graph:IGraph; + var first:IGraphNode; + var discovered = new Set(); + var toVisit = new Queue>(); + + public function new(node:IGraphNode) { + this.graph = node.graph; + toVisit.push(node); + } + + inline public function hasNext():Bool { + return toVisit.length > 0; + } + + inline public function next():IGraphNode { + var nextNode = toVisit.pop(); + discovered.add(nextNode.label); + + for (node in graph.outNeighbors(nextNode)) { + if (discovered.exists(node.label)) { + continue; + } + toVisit.push(node); + discovered.add(node.label); + } + + return nextNode; + } +} diff --git a/src/dropecho/ds/graph/DFIterator.hx b/src/dropecho/ds/graph/DFIterator.hx new file mode 100644 index 0000000..d04b9b8 --- /dev/null +++ b/src/dropecho/ds/graph/DFIterator.hx @@ -0,0 +1,34 @@ +package dropecho.ds.graph; + +import dropecho.ds.IGraphNode; + +class DFIterator { + var graph:IGraph; + var first:IGraphNode; + var discovered = new Set(); + var toVisit = new Stack>(); + + public function new(node:IGraphNode) { + this.graph = node.graph; + toVisit.push(node); + } + + public function hasNext():Bool { + return toVisit.length > 0; + } + + public function next():IGraphNode { + var nextNode = toVisit.pop(); + discovered.add(nextNode.label); + + for (node in graph.outNeighbors(nextNode)) { + if (discovered.exists(node.label)) { + continue; + } + toVisit.push(node); + discovered.add(node.label); + } + + return nextNode; + } +} diff --git a/src/dropecho/ds/graph/Grammar.hx b/src/dropecho/ds/graph/Grammar.hx deleted file mode 100644 index c9ba04c..0000000 --- a/src/dropecho/ds/graph/Grammar.hx +++ /dev/null @@ -1,35 +0,0 @@ -package dropecho.ds.graph; - -@:expose -class Grammar { - // public static function Rewrite(node:GraphNode) {} - - public static function replace(node:GraphNode, newNode:GraphNode) { - - // var edgesFromNode = node.graph.edges.get(node.id); - - - //TODO: Get all nodes which have edges to this node. - // for(k=>v in node.graph.edges.keyValueIterator) { - // trace(v); - // } - // var edgesToNode = node.graph.edges.keyValueIterator - - // node.graph.remove(node.id); - } - - // public static function depthFirst(node:GraphNode) { - // var visited = new Array(); - // - // if (visited.indexOf(node.id) == -1) { - // visited.push(node.id); - // } else { - // return null; - // } - // for (n in node.neighbors()) { - // depthFirst(n); - // } - // - // return visited; - // } -} diff --git a/src/dropecho/ds/graph/Search.hx b/src/dropecho/ds/graph/Search.hx index 77d59f4..0435ec8 100644 --- a/src/dropecho/ds/graph/Search.hx +++ b/src/dropecho/ds/graph/Search.hx @@ -6,7 +6,7 @@ using Lambda; @:struct class NodeDist { - public var node:GraphNode; + public var node:IGraphNode; public var dist:Float; public function new(node, dist) { @@ -17,8 +17,8 @@ class NodeDist { @:struct class SearchResult { - public var path:AbstractMap, String>; - public var distances:AbstractMap, Float>; + public var path:AbstractMap, String>; + public var distances:AbstractMap, Float>; public function new(path, distances) { this.path = path; @@ -36,11 +36,11 @@ class Search { * @param [distCalc] - A distance calculation function. (optional) * @return An object with the path and distances to every node. */ - public static function dijkstra(node:GraphNode, ?distCalc:(a:GraphNode, b:GraphNode) -> Float):SearchResult { + public static function dijkstra(node:IGraphNode, ?distCalc:(a:IGraphNode, b:IGraphNode) -> Float):SearchResult { var compare = (a, b) -> (Reflect.compare(a.dist, b.dist) < 0); var queue = new Heap>(compare); - var dist = new AbstractMap, Float>(); - var prev = new AbstractMap, String>(); + var dist = new AbstractMap, Float>(); + var prev = new AbstractMap, String>(); var graph = node.graph; @@ -63,8 +63,8 @@ class Search { while (queue.size() > 0) { var minDistNode = queue.pop().node; - var existingIds = queue.elements.map(x -> x.node.id); - var filter = (id, data) -> existingIds.indexOf(id) >= 0; + var existingLabels = queue.elements.map(x -> x.node.label); + var filter = (label, data) -> existingLabels.indexOf(label) >= 0; var neighbors = graph.neighbors(minDistNode, filter); for (neighbor in neighbors) { @@ -72,7 +72,7 @@ class Search { var distanceToNeighbor = dist[minDistNode] + distCalc(minDistNode, neighbor); if (distanceToNeighbor <= dist[neighbor]) { dist[neighbor] = distanceToNeighbor; - prev[neighbor] = minDistNode.id; + prev[neighbor] = minDistNode.label; var existing = queue.elements.find(x -> x.node == neighbor); // queue.set_value_obj(existing, {node: neighbor, dist: dist[neighbor]}); diff --git a/src/dropecho/ds/graph/Traversal.hx b/src/dropecho/ds/graph/Traversal.hx deleted file mode 100644 index 36c0b36..0000000 --- a/src/dropecho/ds/graph/Traversal.hx +++ /dev/null @@ -1,76 +0,0 @@ -package dropecho.ds.graph; - -@:expose -class Traversal { - /* - procedure BFS(G, start_v) is - let Q be a queue - label start_v as discovered - Q.enqueue(start_v) - while Q is not empty do - v := Q.dequeue() - if v is the goal then - return v - for all edges from v to w in G.adjacentEdges(v) do - if w is not labeled as discovered then - label w as discovered - w.parent := v - Q.enqueue(w) - */ - /** - * Runs a breadth first traversal on a graph. - * [Wikipedia Breadth First Search](https://en.wikipedia.org/wiki/Breadth-first_search) - * - * @param node - The node to start the BFS traversal from. - * @return The array of node ids in visitation order.. - */ - public static function breadthFirst(node:GraphNode):Array { - var graph = node.graph; - var visited = new Array(); - var toVisit = new Array>(); - - toVisit.push(node); - - while (toVisit.length > 0) { - var next = toVisit.shift(); - - if (!visited.contains(next.id)) { - visited.push(next.id); - for (n in graph.neighbors(next)) { - toVisit.push(n); - } - } - } - - return visited; - } - - /* - procedure DFS(G, v) is - label v as discovered - for all directed edges from v to w that are in G.adjacentEdges(v) do - if vertex w is not labeled as discovered then - recursively call DFS(G, w) - */ - /** - * Runs a depth first traversal on a graph. - * [Wikipedia Depth First Search](https://en.wikipedia.org/wiki/Depth-first_search) - * @param node - The node to start the DFS traversal from. - * @return The array of node ids in visitation order.. - */ - public static function depthFirst(node:GraphNode):Array { - var graph = node.graph; - var visited = new Array(); - - if (visited.indexOf(node.id) == -1) { - visited.push(node.id); - } else { - return null; - } - for (n in graph.neighbors(node)) { - depthFirst(n); - } - - return visited; - } -} diff --git a/test/algos/InOrderTraversalTests.hx b/test/algos/InOrderTraversalTests.hx index bced9b5..099061a 100644 --- a/test/algos/InOrderTraversalTests.hx +++ b/test/algos/InOrderTraversalTests.hx @@ -39,10 +39,10 @@ class InOrderTraversalTests extends Test { var visited = iot.run(node1); - Assert.equals(node4.id, visited[0]); - Assert.equals(node2.id, visited[1]); - Assert.equals(node5.id, visited[2]); - Assert.equals(node1.id, visited[3]); - Assert.equals(node3.id, visited[4]); + Assert.equals(node4.label, visited[0]); + Assert.equals(node2.label, visited[1]); + Assert.equals(node5.label, visited[2]); + Assert.equals(node1.label, visited[3]); + Assert.equals(node3.label, visited[4]); } } diff --git a/test/algos/PostOrderTraversalTests.hx b/test/algos/PostOrderTraversalTests.hx index 73c60d5..d514145 100644 --- a/test/algos/PostOrderTraversalTests.hx +++ b/test/algos/PostOrderTraversalTests.hx @@ -38,10 +38,10 @@ class PostOrderTraversalTests extends Test { var visited = trav.run(node1); - Assert.equals(node4.id, visited[0]); - Assert.equals(node5.id, visited[1]); - Assert.equals(node2.id, visited[2]); - Assert.equals(node3.id, visited[3]); - Assert.equals(node1.id, visited[4]); + Assert.equals(node4.label, visited[0]); + Assert.equals(node5.label, visited[1]); + Assert.equals(node2.label, visited[2]); + Assert.equals(node3.label, visited[3]); + Assert.equals(node1.label, visited[4]); } } diff --git a/test/algos/PreOrderTraversalTests.hx b/test/algos/PreOrderTraversalTests.hx index dfcae32..537491e 100644 --- a/test/algos/PreOrderTraversalTests.hx +++ b/test/algos/PreOrderTraversalTests.hx @@ -38,10 +38,10 @@ class PreOrderTraversalTests extends Test { var visited = trav.run(node1); - Assert.equals(node1.id, visited[0]); - Assert.equals(node2.id, visited[1]); - Assert.equals(node4.id, visited[2]); - Assert.equals(node5.id, visited[3]); - Assert.equals(node3.id, visited[4]); + Assert.equals(node1.label, visited[0]); + Assert.equals(node2.label, visited[1]); + Assert.equals(node4.label, visited[2]); + Assert.equals(node5.label, visited[3]); + Assert.equals(node3.label, visited[4]); } } diff --git a/test/bsp/BSPNodeTests.hx b/test/bsp/BSPNodeTests.hx index 649af2b..00204c3 100644 --- a/test/bsp/BSPNodeTests.hx +++ b/test/bsp/BSPNodeTests.hx @@ -9,7 +9,7 @@ class BSPNodeTests extends Test { public function setup() { node = new BSPNode(); - node.id = "TEST_BSP_NODE"; + node.label = "TEST_BSP_NODE"; var tree = new BSPTree(); tree.addNode(node); diff --git a/test/bsp/BSPTreeTests.hx b/test/bsp/BSPTreeTests.hx index 95e15b0..7782359 100644 --- a/test/bsp/BSPTreeTests.hx +++ b/test/bsp/BSPTreeTests.hx @@ -19,7 +19,7 @@ class BSPTreeTests extends Test { var root = tree.root; Assert.equals(4, root.value); - Assert.isTrue(tree.nodes.exists(root.id)); + Assert.isTrue(tree.nodes.exists(root.label)); } public function test_getParent() { diff --git a/test/graph/BFSTests.hx b/test/graph/BFSTests.hx deleted file mode 100644 index 10732f5..0000000 --- a/test/graph/BFSTests.hx +++ /dev/null @@ -1,114 +0,0 @@ -package graph; - -import utest.Assert; -import utest.Test; -import dropecho.ds.*; -import dropecho.ds.graph.Traversal; - -class BFSTests extends Test { - var graph:Graph; - - public function setup() { - graph = new Graph(); - } - - public function test_run() { - /******************* - GRAPH - - 1 - / \ - 2 4 - / \ \ - 3 5 - 6 - - *******************/ - - var node1 = new GraphNode(1); - - node1.id = '1'; - var node2 = new GraphNode(1); - node2.id = '2'; - var node3 = new GraphNode(1); - node3.id = '3'; - var node4 = new GraphNode(1); - node4.id = '4'; - var node5 = new GraphNode(1); - node5.id = '5'; - var node6 = new GraphNode(1); - node6.id = '6'; - - graph.addNode(node1); - graph.addNode(node2); - graph.addNode(node3); - graph.addNode(node4); - graph.addNode(node5); - graph.addNode(node6); - - graph.addBiEdge(node1.id, node4.id); - graph.addBiEdge(node1.id, node2.id); - graph.addBiEdge(node2.id, node3.id); - graph.addBiEdge(node2.id, node5.id); - graph.addBiEdge(node4.id, node6.id); - graph.addBiEdge(node6.id, node5.id); - - var visited = Traversal.breadthFirst(node1); - - Assert.isTrue(node1.id == visited[0]); - Assert.isTrue(node2.id == visited[1]); - Assert.isTrue(node4.id == visited[2]); - Assert.isTrue(node3.id == visited[3]); - Assert.isTrue(node5.id == visited[4]); - Assert.isTrue(node6.id == visited[5]); - } - - // function traversal() { - // [>****************** - // GRAPH - // - // 1 - // / \ - // 2 3 - // / \ \ - // 4 5 6 - // - // *******************/ - // - // var node1 = new GraphNode(1); - // node1.id = '1'; - // var node2 = new GraphNode(1); - // node2.id = '2'; - // var node3 = new GraphNode(1); - // node3.id = '3'; - // var node4 = new GraphNode(1); - // node4.id = '4'; - // var node5 = new GraphNode(1); - // node5.id = '5'; - // var node6 = new GraphNode(1); - // node6.id = '6'; - // - // graph.addNode(node1); - // graph.addNode(node2); - // graph.addNode(node3); - // graph.addNode(node4); - // graph.addNode(node5); - // graph.addNode(node6); - // - // graph.addBiEdge(node1.id, node3.id); - // graph.addBiEdge(node1.id, node2.id); - // graph.addBiEdge(node2.id, node5.id); - // graph.addBiEdge(node2.id, node4.id); - // graph.addBiEdge(node3.id, node6.id); - // - // var visited = Traversal.breadthFirst(node1); - // - // trace("visited bfs: " + visited); - // - // Assert.isTrue(node1.id == visited[0]); - // Assert.isTrue(node2.id == visited[1]); - // Assert.isTrue(node3.id == visited[2]); - // Assert.isTrue(node4.id == visited[3]); - // Assert.isTrue(node5.id == visited[4]); - // Assert.isTrue(node6.id == visited[5]); - // } -} diff --git a/test/graph/DFSTests.hx b/test/graph/DFSTests.hx deleted file mode 100644 index 603f299..0000000 --- a/test/graph/DFSTests.hx +++ /dev/null @@ -1,111 +0,0 @@ -package graph; - -import utest.Assert; -import utest.Test; -import dropecho.ds.*; -import dropecho.ds.algos.*; -import dropecho.ds.graph.Traversal; - -class DFSTests extends Test { - var graph:Graph; - - public function setup() { - graph = new Graph(); - } - - // public function test_run() { - /****************** - GRAPH - - 1 - / \ - 2 4 - / \ \ - 3 5 - 6 - - *****************/ - // var node1 = new GraphNode(1); - // - // node1.id = '1'; - // var node2 = new GraphNode(1); - // node2.id = '2'; - // var node3 = new GraphNode(1); - // node3.id = '3'; - // var node4 = new GraphNode(1); - // node4.id = '4'; - // var node5 = new GraphNode(1); - // node5.id = '5'; - // var node6 = new GraphNode(1); - // node6.id = '6'; - // - // graph.addNode(node1); - // graph.addNode(node2); - // graph.addNode(node3); - // graph.addNode(node4); - // graph.addNode(node5); - // graph.addNode(node6); - // - // graph.addBiEdge(node1.id, node4.id); - // graph.addBiEdge(node1.id, node2.id); - // graph.addBiEdge(node2.id, node3.id); - // graph.addBiEdge(node2.id, node5.id); - // graph.addBiEdge(node4.id, node6.id); - // graph.addBiEdge(node6.id, node5.id); - // - // var visited = Traversal.depthFirst(node1); - // - // Assert.equals(node1.id, visited[0]); - // Assert.equals(node2.id, visited[1]); - // Assert.equals(node3.id, visited[2]); - // Assert.equals(node5.id, visited[3]); - // Assert.equals(node6.id, visited[4]); - // Assert.equals(node4.id, visited[5]); - // } - // function test_traversal() { - /****************** - GRAPH - - 1 - / \ - 2 3 - / \ \ - 4 5 6 - - */ - // var node1 = new GraphNode(1); - // - // node1.id = '1'; - // var node2 = new GraphNode(1); - // node2.id = '2'; - // var node3 = new GraphNode(1); - // node3.id = '3'; - // var node4 = new GraphNode(1); - // node4.id = '4'; - // var node5 = new GraphNode(1); - // node5.id = '5'; - // var node6 = new GraphNode(1); - // node6.id = '6'; - // - // graph.addNode(node1); - // graph.addNode(node2); - // graph.addNode(node3); - // graph.addNode(node4); - // graph.addNode(node5); - // graph.addNode(node6); - // - // graph.addBiEdge(node1.id, node3.id); - // graph.addBiEdge(node1.id, node2.id); - // graph.addBiEdge(node2.id, node5.id); - // graph.addBiEdge(node2.id, node4.id); - // graph.addBiEdge(node3.id, node6.id); - // - // var visited = Traversal.depthFirst(node1); - // - // Assert.equals(node1.id, visited[0]); - // Assert.equals(node2.id, visited[1]); - // Assert.equals(node4.id, visited[2]); - // Assert.equals(node5.id, visited[3]); - // Assert.equals(node3.id, visited[4]); - // Assert.equals(node6.id, visited[5]); - // } -} diff --git a/test/graph/DijkstraTests.hx b/test/graph/DijkstraTests.hx index 2479ae7..935fe77 100644 --- a/test/graph/DijkstraTests.hx +++ b/test/graph/DijkstraTests.hx @@ -32,22 +32,22 @@ class DijkstraTests extends Test { var node5 = graph.createNode(1); var node6 = graph.createNode(1); - graph.addBiEdge(node1.id, node4.id); - graph.addBiEdge(node1.id, node2.id); - graph.addBiEdge(node2.id, node3.id); - graph.addBiEdge(node2.id, node5.id); - graph.addBiEdge(node4.id, node6.id); - graph.addBiEdge(node6.id, node5.id); + graph.addBiEdge(node1.label, node4.label); + graph.addBiEdge(node1.label, node2.label); + graph.addBiEdge(node2.label, node3.label); + graph.addBiEdge(node2.label, node5.label); + graph.addBiEdge(node4.label, node6.label); + graph.addBiEdge(node6.label, node5.label); var results = Search.dijkstra(node1); var path = results.path; Assert.isFalse(path.exists(node1)); - Assert.equals(node1.id, path[node4]); - Assert.equals(node1.id, path[node2]); - Assert.equals(node4.id, path[node6]); - Assert.equals(node2.id, path[node3]); - Assert.equals(node2.id, path[node5]); + Assert.equals(node1.label, path[node4]); + Assert.equals(node1.label, path[node2]); + Assert.equals(node4.label, path[node6]); + Assert.equals(node2.label, path[node3]); + Assert.equals(node2.label, path[node5]); } function test_traversal() { @@ -67,33 +67,33 @@ class DijkstraTests extends Test { var node7 = graph.createNode(1); var node8 = graph.createNode(1); - graph.addBiEdge(node1.id, node2.id); - graph.addBiEdge(node1.id, node4.id); + graph.addBiEdge(node1.label, node2.label); + graph.addBiEdge(node1.label, node4.label); - graph.addBiEdge(node2.id, node1.id); - graph.addBiEdge(node2.id, node3.id); - graph.addBiEdge(node2.id, node5.id); + graph.addBiEdge(node2.label, node1.label); + graph.addBiEdge(node2.label, node3.label); + graph.addBiEdge(node2.label, node5.label); - graph.addBiEdge(node3.id, node2.id); - graph.addBiEdge(node3.id, node6.id); + graph.addBiEdge(node3.label, node2.label); + graph.addBiEdge(node3.label, node6.label); - graph.addBiEdge(node4.id, node1.id); - graph.addBiEdge(node4.id, node5.id); - graph.addBiEdge(node4.id, node7.id); + graph.addBiEdge(node4.label, node1.label); + graph.addBiEdge(node4.label, node5.label); + graph.addBiEdge(node4.label, node7.label); - graph.addBiEdge(node5.id, node2.id); - graph.addBiEdge(node5.id, node4.id); - graph.addBiEdge(node5.id, node6.id); - graph.addBiEdge(node5.id, node8.id); + graph.addBiEdge(node5.label, node2.label); + graph.addBiEdge(node5.label, node4.label); + graph.addBiEdge(node5.label, node6.label); + graph.addBiEdge(node5.label, node8.label); - graph.addBiEdge(node6.id, node3.id); - graph.addBiEdge(node6.id, node5.id); + graph.addBiEdge(node6.label, node3.label); + graph.addBiEdge(node6.label, node5.label); - graph.addBiEdge(node7.id, node4.id); - graph.addBiEdge(node7.id, node8.id); + graph.addBiEdge(node7.label, node4.label); + graph.addBiEdge(node7.label, node8.label); - graph.addBiEdge(node8.id, node7.id); - graph.addBiEdge(node8.id, node5.id); + graph.addBiEdge(node8.label, node7.label); + graph.addBiEdge(node8.label, node5.label); var results = Search.dijkstra(node1); var dist = results.distances; diff --git a/test/graph/GrammarTests.hx b/test/graph/GrammarTests.hx deleted file mode 100644 index 0956349..0000000 --- a/test/graph/GrammarTests.hx +++ /dev/null @@ -1,36 +0,0 @@ -package graph; - -import utest.Assert; -import utest.Test; -import dropecho.ds.Graph; -import dropecho.ds.GraphNode; - -class GrammarTests extends Test { - var graph:Graph; - - public function setup() { - graph = new Graph(); - } - - public function test_createNode() { - var node = graph.createNode(4); - - Assert.equals(4, node.value); - Assert.isTrue(graph.nodes.exists(node.id)); - } - - public function replace() { - var node = graph.addNode(new GraphNode(4, "node")); - var node2 = graph.addNode(new GraphNode(4, "node2")); - var node3 = graph.addNode(new GraphNode(3, "node3")); - - graph.addBiEdge(node.id, node2.id); - graph.addBiEdge(node3.id, node2.id); - graph.addUniEdge(node3.id, node.id); - - // Grammar.replace(node, new GraphNode()); - - // Assert.equals(4, node.value); - // Assert.isTrue(graph.nodes.exists(node.id)); - } -} diff --git a/test/graph/GraphNodeTests.hx b/test/graph/GraphNodeTests.hx index de48e33..2ac2f3c 100644 --- a/test/graph/GraphNodeTests.hx +++ b/test/graph/GraphNodeTests.hx @@ -16,13 +16,13 @@ class GraphNodeTests extends Test { Assert.equals(value, node.value); } - public function test_id_is_unique() { + public function test_label_is_unique() { var nodes = [for (_ in 0...10) new GraphNode(3)]; for (node in nodes) { for (other in nodes) { if (node != other) { - Assert.notEquals(node.id, other.id); + Assert.notEquals(node.label, other.label); } } } diff --git a/test/graph/GraphTests.hx b/test/graph/GraphTests.hx index a517a75..e43dfee 100644 --- a/test/graph/GraphTests.hx +++ b/test/graph/GraphTests.hx @@ -20,42 +20,42 @@ class GraphTests extends Test { var node = graph.createNode(4); Assert.equals(4, node.value); - Assert.isTrue(graph.nodes.exists(node.id)); + Assert.isTrue(graph.nodes.exists(node.label)); } public function test_addNode() { var node = new GraphNode(4); - var inside = graph.addNode(node); + var inslabele = graph.addNode(node); - Assert.equals(node, inside); - Assert.isTrue(graph.nodes.exists(node.id)); + Assert.equals(node, inslabele); + Assert.isTrue(graph.nodes.exists(node.label)); } public function test_addUniEdge() { var node1 = graph.createNode(4); var node2 = graph.createNode(5); - graph.addUniEdge(node1.id, node2.id, 12); + graph.addUniEdge(node1.label, node2.label, 12); - Assert.isTrue(graph.edges.exists(node1.id)); + Assert.isTrue(graph.edges.exists(node1.label)); Assert.equals(node2, graph.outNeighbors(node1)[0]); - Assert.isFalse(graph.edges.exists(node2.id)); - Assert.equals(12, graph.edges.get(node1.id).get(node2.id)); + Assert.isFalse(graph.edges.exists(node2.label)); + Assert.equals(12, graph.edges.get(node1.label).get(node2.label)); } public function test_addBiEdge() { var node1 = graph.createNode(4); var node2 = graph.createNode(5); - graph.addBiEdge(node1.id, node2.id, 12); + graph.addBiEdge(node1.label, node2.label, 12); - Assert.isTrue(graph.edges.exists(node1.id)); + Assert.isTrue(graph.edges.exists(node1.label)); Assert.equals(node2, graph.outNeighbors(node1)[0]); - Assert.equals(12, graph.edges.get(node1.id).get(node2.id)); + Assert.equals(12, graph.edges.get(node1.label).get(node2.label)); - Assert.isTrue(graph.edges.exists(node2.id)); + Assert.isTrue(graph.edges.exists(node2.label)); Assert.equals(node1, graph.outNeighbors(node2)[0]); - Assert.equals(12, graph.edges.get(node2.id).get(node1.id)); + Assert.equals(12, graph.edges.get(node2.label).get(node1.label)); } public function test_remove() { @@ -64,14 +64,14 @@ class GraphTests extends Test { var node3 = graph.createNode(0); var node4 = graph.createNode(0); - graph.addUniEdge(node1.id, node2.id); - graph.addUniEdge(node3.id, node1.id); - graph.addBiEdge(node4.id, node1.id); + graph.addUniEdge(node1.label, node2.label); + graph.addUniEdge(node3.label, node1.label); + graph.addBiEdge(node4.label, node1.label); - graph.remove(node1.id); + graph.remove(node1.label); - Assert.isFalse(graph.nodes.exists(node1.id)); - Assert.isFalse(graph.edges.exists(node1.id)); + Assert.isFalse(graph.nodes.exists(node1.label)); + Assert.isFalse(graph.edges.exists(node1.label)); Assert.isFalse(graph.neighbors(node2).contains(node1)); Assert.isFalse(graph.neighbors(node3).contains(node1)); Assert.isFalse(graph.neighbors(node4).contains(node1)); @@ -82,8 +82,8 @@ class GraphTests extends Test { var node2 = graph.createNode(5); var node3 = graph.createNode(5); - graph.addUniEdge(node1.id, node2.id, 12); - graph.addUniEdge(node1.id, node3.id, 14); + graph.addUniEdge(node1.label, node2.label, 12); + graph.addUniEdge(node1.label, node3.label, 14); var outNeighbors = graph.outNeighbors(node1); @@ -91,26 +91,26 @@ class GraphTests extends Test { Assert.notEquals(-1, outNeighbors.indexOf(node3)); } - public function test_outNeighborIds() { + public function test_outNeighborLabels() { var node1 = graph.createNode(4); var node2 = graph.createNode(5); var node3 = graph.createNode(6); - graph.addUniEdge(node1.id, node2.id, 12); - graph.addUniEdge(node1.id, node3.id, 14); + graph.addUniEdge(node1.label, node2.label, 12); + graph.addUniEdge(node1.label, node3.label, 14); - var outNeighborIds = graph.outNeighborIds(node1); + var outNeighborLabels = graph.outNeighborLabels(node1); - Assert.notEquals(-1, outNeighborIds.indexOf(node2.id)); - Assert.notEquals(-1, outNeighborIds.indexOf(node3.id)); + Assert.notEquals(-1, outNeighborLabels.indexOf(node2.label)); + Assert.notEquals(-1, outNeighborLabels.indexOf(node3.label)); } - public function test_outNeighborIds_when_empty() { + public function test_outNeighborLabels_when_empty() { var node1 = graph.createNode(4); - var outNeighborIds = graph.outNeighborIds(node1); + var outNeighborLabels = graph.outNeighborLabels(node1); - Assert.equals(0, outNeighborIds.length); + Assert.equals(0, outNeighborLabels.length); } public function test_edgeData() { @@ -118,11 +118,11 @@ class GraphTests extends Test { var node2 = graph.createNode(5, "edge_data_test_node_2"); var node3 = graph.createNode(6, "edge_data_test_node_3"); - graph.addUniEdge(node1.id, node2.id, 12); - graph.addUniEdge(node1.id, node3.id, 14); + graph.addUniEdge(node1.label, node2.label, 12); + graph.addUniEdge(node1.label, node3.label, 14); - var node1_to_node2_data = graph.edgeData(node1.id, node2.id); - var node1_to_node3_data = graph.edgeData(node1.id, node3.id); + var node1_to_node2_data = graph.edgeData(node1.label, node2.label); + var node1_to_node3_data = graph.edgeData(node1.label, node3.label); Assert.equals(12, node1_to_node2_data); Assert.equals(14, node1_to_node3_data); @@ -132,7 +132,7 @@ class GraphTests extends Test { var node1 = graph.createNode(4); var node2 = graph.createNode(5); - var node1_to_node2_data = graph.edgeData(node1.id, node2.id); + var node1_to_node2_data = graph.edgeData(node1.label, node2.label); var nul:Null = null; Assert.equals(nul, node1_to_node2_data); @@ -144,7 +144,7 @@ class GraphTests extends Test { var node1 = graph.createNode(4, "a"); var node2 = graph.createNode(5, "b"); - graph.addUniEdge(node1.id, node2.id); + graph.addUniEdge(node1.label, node2.label); Assert.equals(expected, graph.toDot()); } diff --git a/test/graph/IteratorTests.hx b/test/graph/IteratorTests.hx new file mode 100644 index 0000000..63df31b --- /dev/null +++ b/test/graph/IteratorTests.hx @@ -0,0 +1,79 @@ +package graph; + +import dropecho.ds.graph.DFIterator; +import utest.Assert; +import utest.Test; +import dropecho.ds.*; +import dropecho.ds.graph.BFIterator; + +class IteratorTests extends Test { + var graph:Graph; + + public function setup() { + graph = new Graph(); + /******************* + GRAPH + + 1 + / \ + 2 4 + / \ \ + 3 5 - 6 + + *******************/ + + var node1 = new GraphNode(1); + + node1.label = '1'; + var node2 = new GraphNode(1); + node2.label = '2'; + var node3 = new GraphNode(1); + node3.label = '3'; + var node4 = new GraphNode(1); + node4.label = '4'; + var node5 = new GraphNode(1); + node5.label = '5'; + var node6 = new GraphNode(1); + node6.label = '6'; + + graph.addNode(node1); + graph.addNode(node2); + graph.addNode(node3); + graph.addNode(node4); + graph.addNode(node5); + graph.addNode(node6); + + graph.addBiEdge(node1.label, node4.label); + graph.addBiEdge(node1.label, node2.label); + + graph.addBiEdge(node2.label, node3.label); + graph.addBiEdge(node2.label, node5.label); + + graph.addBiEdge(node4.label, node6.label); + graph.addBiEdge(node6.label, node5.label); + } + + public function test_bf_iterator() { + var iterator = new BFIterator(graph.nodes.get('1')); + var nodes = [1, 2, 4, 3, 5, 6]; + var i = 0; + + for (node in iterator) { + Assert.equals(node.label, Std.string(nodes[i])); + i++; + } + } + + public function test_df_iterator() { + var iterator = new DFIterator(graph.nodes.get('1')); + + // Start at one, and go df on "last" in. + var nodes = [1, 4, 6, 5, 2, 3]; + var i = 0; + + for (node in iterator) { + Assert.equals(node.label, Std.string(nodes[i])); + i++; + } + } +}