All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.javagimmicks.graph.routing.DijkstraRouteFinder Maven / Gradle / Ivy

There is a newer version: 0.99-alpha1
Show newest version
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