diff --git a/Diagrams/PathTaker.vsdx b/Diagrams/PathTaker.vsdx index c7d4318..f2b98f2 100644 Binary files a/Diagrams/PathTaker.vsdx and b/Diagrams/PathTaker.vsdx differ diff --git a/Graph/src/algorithms/Dijkstra/DijkstraAlgorithm.java b/Graph/src/algorithms/Dijkstra/DijkstraAlgorithm.java index 2615f52..36459c4 100644 --- a/Graph/src/algorithms/Dijkstra/DijkstraAlgorithm.java +++ b/Graph/src/algorithms/Dijkstra/DijkstraAlgorithm.java @@ -1,9 +1,44 @@ package algorithms.Dijkstra; import elements.Graph; +import elements.GraphNode; +import java.util.ArrayList; + +/** + * A type that calculates the path and distance from the source node to any other node that the source node is connected to(Including the target node) + * It's methods return an instance PathData. + */ public class DijkstraAlgorithm { - public static void FindShortestPath(Graph graph, String sourceNodeIdentification, String targetNodeIdentification) { + public static PathData FindShortestPath(Graph graph, String sourceNodeIdentifier, String targetNodeIdentifier) throws ArrayStoreException { + return FindShortestPath(graph, graph.getNode(sourceNodeIdentifier), graph.getNode(targetNodeIdentifier)); + } + + public static PathData FindShortestPath(Graph graph, GraphNode sourceNode, GraphNode targetNode) throws ArrayStoreException { + if (graph.getNodes().size() == 0) throw new ArrayStoreException(); + ArrayList nodes = graph.getNodes(); + ArrayList navigatedNodes = new ArrayList<>(); + PathData pathData = new PathData(nodes, sourceNode, targetNode); + + nodes.remove(sourceNode); + navigatedNodes.add(sourceNode); + + GraphNode leastDistantNode = pathData.GetClosestNode(nodes); + + nodes.remove(leastDistantNode); + navigatedNodes.add(leastDistantNode); + + for (GraphNode node : leastDistantNode.getAttachedNodes().keySet()) { + double currentDistance = pathData.GetDistanceToNode(leastDistantNode) + + leastDistantNode.getAttachedNodes().get(node).getWeight(); + if (currentDistance < pathData.GetDistanceToNode(node)){ + pathData.distances.put(node, currentDistance); + node.setPreviousNodeInPath(leastDistantNode); + break; + } + } + + return pathData; } } diff --git a/Graph/src/algorithms/Dijkstra/DijkstraAlgorithmTest.java b/Graph/src/algorithms/Dijkstra/DijkstraAlgorithmTest.java index 4227371..e858f07 100644 --- a/Graph/src/algorithms/Dijkstra/DijkstraAlgorithmTest.java +++ b/Graph/src/algorithms/Dijkstra/DijkstraAlgorithmTest.java @@ -2,6 +2,7 @@ import algorithms.GraphBuilder; import elements.Graph; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -15,11 +16,25 @@ void SetUp() { } + @AfterEach + void TearDown() { + + } + @Test - void Test1() { + void GraphWithNoNodes_ThrowsArgumentException() { graph = GraphBuilder.Build().WithNodes(0).getGraph(); - Assertions.assertThrows(IllegalArgumentException.class, - () -> DijkstraAlgorithm.FindShortestPath(graph, "0", "0")); + Assertions.assertThrows(ArrayStoreException.class, () -> DijkstraAlgorithm.FindShortestPath(graph, "0", "0")); + } + + @Test + void GraphWith1Node_ReturnsPathWithOneNode() { + graph = GraphBuilder.Build().WithNodes(1).getGraph(); + + PathData pathData = DijkstraAlgorithm.FindShortestPath(graph, "0", "0"); + + Assertions.assertEquals(1, pathData.distances.size()); + Assertions.assertEquals(0, pathData.GetDistanceToNode(graph.getNode("0"))); } } \ No newline at end of file diff --git a/Graph/src/algorithms/Dijkstra/PathData.java b/Graph/src/algorithms/Dijkstra/PathData.java new file mode 100644 index 0000000..5ac3b69 --- /dev/null +++ b/Graph/src/algorithms/Dijkstra/PathData.java @@ -0,0 +1,63 @@ +package algorithms.Dijkstra; + +import elements.GraphNode; + +import java.util.ArrayList; +import java.util.HashMap; + +/** + * A Type that contains and returns the path and distance from the source node to any other node in the graph that the source node is connected to(Including Target Node). + */ +public class PathData { + GraphNode sourceNode; + GraphNode targetNode; + HashMap distances; + + public PathData(ArrayList nodes, GraphNode sourceNode, GraphNode targetNode) { + this.sourceNode = sourceNode; + this.targetNode = targetNode; + distances = new HashMap<>(); + for (GraphNode node : nodes) + distances.put(node, Double.POSITIVE_INFINITY); + sourceNode.setPreviousNodeInPath(null); + distances.put(sourceNode, 0.0); + } + + /** + * @return + */ + public ArrayList GetPathNodesToTargetNode() { + return null; + } + + /** + * @return + */ + public ArrayList GetPathNodesToNode(GraphNode node) { + return null; + } + + + /** + * @return + */ + public double GetDistanceToNode(GraphNode node) { + return 0; + } + + public GraphNode GetClosestNode(ArrayList nodes) { + double minDistance = Double.POSITIVE_INFINITY; + + GraphNode closestNode = sourceNode; + for (GraphNode graphNode : nodes) { + if (graphNode != sourceNode) { + double distance = distances.get(graphNode); + if (distance < minDistance) { + minDistance = distance; + closestNode = graphNode; + } + } + } + return closestNode; + } +} diff --git a/Graph/src/algorithms/GraphBuilder.java b/Graph/src/algorithms/GraphBuilder.java index fb33ff1..b361db8 100644 --- a/Graph/src/algorithms/GraphBuilder.java +++ b/Graph/src/algorithms/GraphBuilder.java @@ -16,7 +16,7 @@ public static GraphBuilder Build() { public GraphBuilder WithNodes(int nodeCount) { for (int index = 0; index < nodeCount; index++) - graph.addNode(String.format("%d", nodeCount)); + graph.addNode(index + ""); return this; } diff --git a/Graph/src/elements/Graph.java b/Graph/src/elements/Graph.java index 866450b..600b314 100644 --- a/Graph/src/elements/Graph.java +++ b/Graph/src/elements/Graph.java @@ -1,14 +1,13 @@ package elements; import java.util.ArrayList; -import java.util.List; /** * The type Graph. */ public class Graph { - private List nodes = new ArrayList<>(); - private List edges = new ArrayList<>(); + private ArrayList nodes = new ArrayList<>(); + private ArrayList edges = new ArrayList<>(); /** * Gets nodes. @@ -16,7 +15,7 @@ public class Graph { * @return the nodes */ - public List getNodes() { + public ArrayList getNodes() { return nodes; } @@ -26,7 +25,7 @@ public List getNodes() { * @param nodes the nodes */ - public void setNodes(List nodes) { + public void setNodes(ArrayList nodes) { this.nodes = nodes; } @@ -36,7 +35,7 @@ public void setNodes(List nodes) { * @return the edges */ - public List getEdges() { + public ArrayList getEdges() { return edges; } @@ -46,7 +45,7 @@ public List getEdges() { * @param edges the edges */ - public void setEdges(List edges) { + public void setEdges(ArrayList edges) { this.edges = edges; } @@ -57,16 +56,9 @@ public void setEdges(List edges) { */ public GraphNode addNode(String id) { - /* - * Instantiate new graph node and add it - * to the main nodes array list - */ GraphNode newNode = new GraphNode(id); nodes.add(newNode); - /* - * Return the new node - */ return newNode; } @@ -78,22 +70,11 @@ public GraphNode addNode(String id) { */ public GraphEdge addDirectionalEdge(double weight, GraphNode source, GraphNode target) { - /* - * Instantiate a new graph edge and - * add it to the main edges array list - */ GraphEdge newEdge = new GraphEdge(weight, source, target); edges.add(newEdge); - /* - * Add the target node to the attached nodes array list - * of the source node - */ attachNodes(source, target, newEdge); - /* - * Return the new graph edge - */ return newEdge; } @@ -106,26 +87,15 @@ public GraphEdge addDirectionalEdge(double weight, GraphNode source, GraphNode t */ public NonDirectionalEdge addNonDirectionalEdge(double weight, GraphNode source, GraphNode target) { - /* - * Instantiate two new graph edges, one from the source node to the target - * and the other one from target node to the source. - * Then add both of the edges to the main edges array list - */ + GraphEdge edgeOne = addDirectionalEdge(weight, source, target); GraphEdge edgeTwo = addDirectionalEdge(weight, target, source); edges.add(edgeOne); edges.add(edgeTwo); - /* - * Attach the nodes together - */ attachNodes(source, target, edgeOne); attachNodes(target, source, edgeTwo); - /* - * Instantiate a new non-directional edge - * with the two directional edges already instantiated and return the edge - */ return new NonDirectionalEdge(edgeOne, edgeTwo); } @@ -174,18 +144,9 @@ public void removeNode(GraphNode node) { */ public void removeDirectionalEdge(GraphEdge edge) { - /* - * Remove the edge from the main graph edges array list - */ edges.remove(edge); - /* - * Remove the target node from the attached nodes array list - * of the source node - */ detachNodes(edge.getSourceNode(), edge.getTargetNode()); - - } /** @@ -197,4 +158,10 @@ public void removeDirectionalEdge(GraphEdge edge) { public void removeNonDirectionalEdge(NonDirectionalEdge edge) { } + + public GraphNode getNode(String nodeIdentifier) { + for (GraphNode node : nodes) + if (node.getIdentifier().equals(nodeIdentifier)) return node; + return null; + } }