net.sf.javagimmicks.graph.routing.DijkstraRouteFinder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gimmicks Show documentation
Show all versions of gimmicks Show documentation
Utility classes, APIs and tools for Java
package net.sf.javagimmicks.graph.routing;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sf.javagimmicks.graph.Edge;
import net.sf.javagimmicks.graph.Graph;
import net.sf.javagimmicks.graph.WeightedEdge;
/**
* An implementation of {@link RouteFinder} that uses Dijkstra's
* algorithm for finding {@link Route}s.
*/
public class DijkstraRouteFinder> extends
AbstractRouteFinder
{
/**
* Creates a new instance for the given {@link Graph}.
*
* @param graph
* the {@link Graph} to create the instance for
*/
public DijkstraRouteFinder(final Graph graph)
{
super(graph);
}
@Override
public Route findRoute(final VertexType source, final VertexType target)
{
final Map> result = new HashMap>();
findRoutes(_graph, source, result, target);
return result.get(target);
}
@Override
public Map> findRoutes(final VertexType source)
{
final Map> result = new HashMap>();
findRoutes(_graph, source, result, null);
return result;
}
protected static > void findRoutes(final Graph graph, final V source,
final Map> routes, final V optionalTargetVertex)
{
final Map costs = new HashMap();
costs.put(source, 0.0);
final Map previous = new HashMap();
doFindRoutes(graph, costs, previous, optionalTargetVertex);
if (optionalTargetVertex == null)
{
for (final V target : previous.keySet())
{
createAddRoute(routes, costs, previous, target);
}
}
else
{
createAddRoute(routes, costs, previous, optionalTargetVertex);
}
}
protected static > void doFindRoutes(final Graph graph, final Map costs,
final Map previous, final V optionalTargetVertex)
{
final List vertexList = new ArrayList(graph.vertexSet());
sortVerticesByCost(vertexList, costs);
while (!vertexList.isEmpty())
{
final V currentVertex = vertexList.remove(0);
final Double currentCost = costs.get(currentVertex);
if (currentCost == null)
{
break;
}
for (final E edge : graph.edgesOf(currentVertex))
{
final V targetVertex = edge.getOutgoingVertex(currentVertex);
final double targetNewCost = currentCost +
((edge instanceof WeightedEdge, ?>) ? ((WeightedEdge) edge).getCost() : 1.0);
final Double targetCurrentCost = costs.get(targetVertex);
if (targetCurrentCost == null || targetNewCost < targetCurrentCost)
{
costs.put(targetVertex, targetNewCost);
previous.put(targetVertex, edge);
sortVerticesByCost(vertexList, costs);
}
if (optionalTargetVertex != null && optionalTargetVertex.equals(targetVertex))
{
return;
}
}
}
}
protected static > void createAddRoute(final Map> routes,
final Map costs, final Map previous, final V target)
{
// Skip if route is already there
if (routes.containsKey(target))
{
return;
}
final E edge = previous.get(target);
// Trivial case - the source vertex itself
if (edge == null)
{
routes.put(target, new DefaultRoute(target, target));
return;
}
// Get the source vertex and (optionally build the route for it)
final V source = edge.getOutgoingVertex(target);
createAddRoute(routes, costs, previous, source);
// Build a new route by adding the current edge to the route of the
// previous node
final Route sourceRoute = routes.get(source);
final DefaultRoute newRoute = new DefaultRoute(sourceRoute.getSourceVertex(), target);
newRoute.addAll(sourceRoute);
newRoute.add(edge);
routes.put(target, newRoute);
}
protected static void sortVerticesByCost(final List vertexList, final Map costs)
{
Collections.sort(vertexList, new DistComparator(costs));
}
protected static final class DistComparator implements Comparator
{
protected final Map _costs;
public DistComparator(final Map costs)
{
_costs = costs;
}
@Override
public int compare(final V v1, final V v2)
{
final Double d1 = _costs.get(v1);
final Double d2 = _costs.get(v2);
if (d1 == null)
{
return d2 == null ? 0 : 1;
}
else if (d2 == null)
{
return -1;
}
else
{
return d1.compareTo(d2);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy