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

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

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.AbstractRouteFinder;
import net.sf.javagimmicks.graph.DefaultRoute;
import net.sf.javagimmicks.graph.Edge;
import net.sf.javagimmicks.graph.Graph;
import net.sf.javagimmicks.graph.Route;
import net.sf.javagimmicks.graph.WeightedEdge;

public class DijkstraRouteFinder> extends AbstractRouteFinder
{
   public static > DijkstraRouteFinder createInstance(Graph graph)
   {
      return new DijkstraRouteFinder(graph);
   }
   
   public DijkstraRouteFinder(Graph graph)
   {
      super(graph);
   }

   public Route findRoute(V source, V target)
   {
      final Map> result = new HashMap>();
      findRoutes(_graph, source, result, target);
      
      return result.get(target);
   }

   public Map> findRoutes(V source)
   {
      final Map> result = new HashMap>();
      findRoutes(_graph, source, result, null);
      
      return result;
   }

   public static > void findRoutes(Graph graph, V source, Map> routes, 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(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, V optionalTargetVertex)
   {
      final List vertexList = new ArrayList(graph.vertexSet());
      sortVertecesByCost(vertexList, costs);

      while(!vertexList.isEmpty())
      {
         final V currentVertex = vertexList.remove(0);
         final Double currentCost = costs.get(currentVertex);
         
         if(currentCost == null)
         {
            break;
         }
         
         for(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);
               
               sortVertecesByCost(vertexList, costs);
            }
            
            if(optionalTargetVertex != null && optionalTargetVertex.equals(targetVertex))
            {
               return;
            }
         }
      }
   }
   
   protected static > void createAddRoute(final Map> routes, final Map costs, final Map previous, 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 sortVertecesByCost(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(Map costs)
      {
         _costs = costs;
      }

      public int compare(V v1, V v2)
      {
         Double d1 = _costs.get(v1);
         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