using System; using System.Collections.Generic; using HeuristicLab.Algorithms.GraphRouting.Interfaces; using HeuristicLab.Algorithms.GraphRouting.PriorityQueues; using HeuristicLab.Problems.RoutePlanning.Interfaces; namespace HeuristicLab.Algorithms.GraphRouting { public class DijkstraAlgorithm : IRouter { private IGraph graph; private IHeap unvisitedNodes; private Dictionary distances; private Dictionary predecessors; public DijkstraAlgorithm(IGraph graph) { this.graph = graph; } #region IRouter Members public long[] Calculate(long sourceNodeId, long targetNodeId) { unvisitedNodes = new BinaryHeap(1000000); // unvisited //unvisitedNodes = new BinomialHeap(); // unvisited //unvisitedNodes = new FibonacciHeap(); // unvisited distances = new Dictionary(); predecessors = new Dictionary(); List resultRoute = new List(); if (sourceNodeId == targetNodeId) { resultRoute.Add(sourceNodeId); return resultRoute.ToArray(); } long currentNode = sourceNodeId; float currentWeight = 0; unvisitedNodes.Insert(currentWeight, currentNode); while (unvisitedNodes.Size > 0) { KeyValuePair data = unvisitedNodes.PeekMin(); unvisitedNodes.RemoveMin(); currentNode = data.Value; currentWeight = data.Key; //-------------- //Logger.LogToFile("cn = " + currentNode + " (" + currentWeight + ")"); //-------------- if (currentNode == targetNodeId) { break; } distances[currentNode] = currentWeight; RelaxNeighbors(currentNode, currentWeight); //-------------- //Logger.LogToFile(""); //-------------- } if (currentNode != targetNodeId) { throw new Exception(string.Format("No route found from {0} to {1}", sourceNodeId, targetNodeId)); } return GetRoute(targetNodeId).ToArray(); } #endregion public void RelaxNeighbors(long nodeId, float weight) { Dictionary currentNeighbors = graph.GetNeighborsWithWeight(nodeId); foreach (KeyValuePair neighbor in currentNeighbors) { float totalWeight = weight + neighbor.Value; if (totalWeight < GetDistance(neighbor.Key)) { if (GetDistance(neighbor.Key) == float.MaxValue) { unvisitedNodes.Insert(totalWeight, neighbor.Key); } else { unvisitedNodes.DecreaseKey(totalWeight, neighbor.Key); } distances[neighbor.Key] = totalWeight; predecessors[neighbor.Key] = nodeId; //-------------- //Logger.LogToFile(" neigb:" + neighbor.Key + " (" + totalWeight + ")"); //-------------- } } } private float GetDistance(long id) { float d; if (distances.TryGetValue(id, out d)) { return d; } else { return float.MaxValue; } } private List GetRoute(long nodeId) { List route = new List(); long current = nodeId; long next; if (!predecessors.TryGetValue(current, out next)) { return null; } route.Add(current); while (predecessors.TryGetValue(current, out next)) { current = predecessors[current]; route.Add(current); } route.Reverse(); return route; } } }