package iamrescue.routing.dijkstra;
import iamrescue.routing.IRoutingAlgorithm;
import iamrescue.routing.dijkstra.SimpleGraph.Node;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javolution.util.FastSet;
import org.jgrapht.util.FibonacciHeap;
import org.jgrapht.util.FibonacciHeapNode;
public class ExperimentalDijkstrasShortestPath implements IRoutingAlgorithm {
// private boolean[] expanded;
private ExperimentalDijkstraSearchNode[] nodes;
private SimpleGraph graph;
private FibonacciHeap<Integer> heap;
public ExperimentalDijkstrasShortestPath(SimpleGraph graph, int source,
ExperimentalDijkstraSearchNode[] nodes) {
this(graph, Collections.singletonList(source), Collections
.singletonList(0.0), nodes);
}
@SuppressWarnings("unchecked")
public ExperimentalDijkstrasShortestPath(SimpleGraph graph,
List<Integer> potentialSources, List<Double> initialCosts,
ExperimentalDijkstraSearchNode[] nodes) {
if (potentialSources.size() != initialCosts.size()) {
throw new IllegalArgumentException("Sources and costs "
+ "must have the same number of elements.");
}
this.nodes = nodes;
this.graph = graph;
heap = new FibonacciHeap<Integer>();
for (int i = 0; i < potentialSources.size(); i++) {
int source = potentialSources.get(i);
double cost = initialCosts.get(i);
FibonacciHeapNode<Integer> firstNode = new FibonacciHeapNode<Integer>(
source, cost);
nodes[source].setValues(cost, -1, firstNode);
heap.insert(firstNode, cost);
}
}
public PathSolution getShortestPath(int destination) {
return getShortestPath(Collections.singleton(destination));
}
private int calculateShortestPath(Set<Integer> targetSet) {
for (int target : targetSet) {
nodes[target].setTerminal(true);
}
int bestSolution = -1;
while (heap.size() > 0) {
FibonacciHeapNode<Integer> min = heap.removeMin();
int index = min.getData();
double cost = min.getKey();
//
if (nodes[index].isTerminalNode()) {
bestSolution = index;
// System.out.println("found");
break;
}
Node graphNode = graph.getNodes().get(index);
// Need this???
nodes[index].markVisited();
// For all neighbours
for (int i = 0; i < graphNode.getNeighbours().size(); i++) {
Node neighbour = graphNode.getNeighbours().get(i);
int neighbourIndex = neighbour.getID();
// Still in heap or unvisited?
if (nodes[neighbourIndex].getCost() == Double.POSITIVE_INFINITY
|| nodes[neighbourIndex].getHeapNode() != null) {
double costToNeighbour = cost + graphNode.getCosts().get(i);
// Better cost?
if (costToNeighbour < nodes[neighbourIndex].getCost()) {
FibonacciHeapNode<Integer> heapNode = nodes[neighbourIndex]
.getHeapNode();
// Check if we have previously inserted this
if (heapNode == null) {
heapNode = new FibonacciHeapNode<Integer>(
neighbourIndex, costToNeighbour);
heap.insert(heapNode, costToNeighbour);
} else {
heap.decreaseKey(heapNode, costToNeighbour);
}
nodes[neighbourIndex].setValues(costToNeighbour, index,
heapNode);
}
}
}
}
for (int target : targetSet) {
nodes[target].setTerminal(false);
}
return bestSolution;
}
/**
* @param targetSet
* @return
*/
public PathSolution getShortestPath(Set<Integer> targetSet) {
int bestSolution = -1;
double bestCost = Double.POSITIVE_INFINITY;
for (int target : targetSet) {
double cost = nodes[target].getCost();
if (cost < bestCost) {
bestCost = cost;
bestSolution = target;
}
}
if (bestSolution == -1) {
bestSolution = calculateShortestPath(targetSet);
}
if (bestSolution == -1) {
return new PathSolution(Double.POSITIVE_INFINITY, new int[0]);
}
List<Integer> path = new LinkedList<Integer>();
int pointer = bestSolution;
while (pointer != -1) {
path.add(pointer);
pointer = nodes[pointer].getPredecessor();
}
int[] pathIDs = new int[path.size()];
int counter = path.size() - 1;
for (int id : path) {
pathIDs[counter] = id;
counter--;
}
return new PathSolution(nodes[bestSolution].getCost(), pathIDs);
}
/*
* (non-Javadoc)
*
* @see newrouting.IRoutingAlgorithm#getShortestPath(java.util.List,
* java.util.List)
*/
@Override
public PathSolution getShortestPath(List<Integer> targetSet,
List<Double> targetCosts) {
for (Double d : targetCosts) {
if (d != 0) {
throw new IllegalArgumentException(
"Still need to implement arbitrary costs for "
+ "normal Dijkstra. Use Bidirectional instead.");
}
}
Set<Integer> targets = new FastSet<Integer>();
targets.addAll(targetSet);
return getShortestPath(targets);
}
}