-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathKShortestPath.java
147 lines (123 loc) · 5.28 KB
/
KShortestPath.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
KShortestPath.java
Author: Shreyas Jayanna
Version 1
Date: 05/15/2015
*/
// Import statements
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Stack;
/**
* Class KShortestPath. This class finds k-shortest paths between a source and a destination.
*/
public class KShortestPath {
RoadGraph graph;
RoadGraph tempGraph;
Connections connections;
DynamicShortestPath dsp;
PriorityQueue<KPath> queue;
int K;
/**
* Constructor
* @param graph Road graph
* @param connections Connections
* @param k k
*/
public KShortestPath(RoadGraph graph, Connections connections, int k) {
this.graph = new RoadGraph(graph);
this.tempGraph = new RoadGraph(graph);
this.connections = new Connections(connections);
this.dsp = new DynamicShortestPath(graph,connections);
this.queue = new PriorityQueue<>();
this.K = k;
}
/**
* This method finds k paths bewteen from and target nodes.
* @param from From node
* @param target Target node
* @param currentEdge Current Edge
* @return Arraylist of paths
*/
public ArrayList<KPath> findPaths(MyNode from, MyNode target, MyEdge currentEdge) {
ArrayList<KPath> paths = null;
int index = 0;
// Get the first path using Dijkstra's algorithm
Stack<MyEdge> newEdges = this.dsp.findShortestPath(from,target,currentEdge);
if(newEdges != null) {
//System.out.println("Found first new path using Dijkstra's - path size is " + newEdges.size());
// Add the shortest path from Dijkstra's into the arraylist
ArrayList<MyEdge> altPath = new ArrayList<>();
while(newEdges.size() > 0) {
altPath.add(newEdges.pop());
}
KPath kPath = new KPath(altPath);
paths = new ArrayList<KPath>();
paths.add(index,kPath);
// First shortest path is added to the list.
// Need to find k-1 more shortest paths and add them to the list in the
// increasing order of shortest paths
for(int k = 1; k < K; ++k) {
// Spur node ranges from the first node to the node before the last node in the previous k-shortest path
for(int i = 0; i < paths.get(k-1).getSize() - 1; ++i) {
// Get spur node
MyNode spurNode = paths.get(k-1).getNode(i);
// Get root path
ArrayList<MyEdge> rootPath = new ArrayList<>(paths.get(k-1).getEdges(i));
for(KPath kpath : paths) {
ArrayList<MyEdge> edges = kpath.getEdges(i);
// Remove the edges from the graph which share the same path as root path
if(rootPath.equals(edges)) {
MyEdge removeEdge = kpath.getEdge(i+1);
this.tempGraph.removeEdge(removeEdge);
}
}
// Remove root path node from the graph except the spur node
for(MyNode node : this.getRootPathNodes(rootPath)) {
if(node != spurNode)
this.tempGraph.removeNode(node);
}
// Create new instance of Dijsktra's with the modified graph
this.dsp = new DynamicShortestPath(this.tempGraph,this.connections);
// Calculate the spur path
Stack<MyEdge> spurPathStack = dsp.findShortestPath(spurNode, target, currentEdge);
if(spurPathStack != null) {
// Create the total path
// Total path = root path + spur path
ArrayList<MyEdge> totalPath = new ArrayList<>(rootPath);
spurPathStack.pop();
while (spurPathStack.size() > 0) {
totalPath.add(spurPathStack.pop());
}
// Create a new k path object with the new k-shortest path
KPath newPath = new KPath(totalPath);
// Add the new path to the priority queue
this.queue.add(newPath);
// Restore the temporary graph as this will be used for next iterations
this.tempGraph = new RoadGraph(this.graph);
}
}
// If there are no k-shortest paths (all paths are exhausted), break
if(this.queue.size() < 1) {
break;
}
// Add the new path to the list which will be returned
paths.add(k,queue.poll());
}
}
// Return the k-shortest paths
return paths;
}
/**
* This method returns the root path nodes
* @param rootPath Root path
* @return Nodes from root path
*/
public ArrayList<MyNode> getRootPathNodes(ArrayList<MyEdge> rootPath) {
ArrayList<MyNode> nodes = new ArrayList<>();
for(MyEdge edge : rootPath) {
nodes.add(edge.getTo());
}
return nodes;
}
}