void handleState(DijkstraState state) { foreach (DijkstraLinkState linkState in state) { LinkEntry entry = links[linkState.Link]; if (entry.WhenUpdated < state.When) { entry.IsBroken = linkState.IsBroken; entry.WhenUpdated = state.When; } } }
void onSendState(TimerEntry entry) { Timer.Schedule(Timer.CurrentTime + Configuration.Protocols.Dijkstra.StateSendingPeriod, onSendState, null); if (!node.IsAvailable) { return; } List <DijkstraLinkState> linkStates = new List <DijkstraLinkState>(); foreach (NetworkInterface netInt in node.NetworkInterfaces.Interfaces.Values) { DijkstraLinkState linkState = new DijkstraLinkState(netInt.Link, netInt.LinkSide.IsBroken); linkStates.Add(linkState); } DijkstraState state = new DijkstraState(Timer.CurrentTime, linkStates.ToArray()); RoutingInfoBundle bundle = new RoutingInfoBundle(node, null, state); broadcast(bundle, null); }
public static Graph RunSolver(Graph graph) { var solution = new Graph(graph.Vertices); DijkstraState state = new DijkstraState(); // Create the states needed for every execution of the Dijkstra algorithm foreach (var terminal in graph.Terminals) state.AddVertexToInterleavingDijkstra(terminal, graph); // Initialize Vertex currentVertex = state.GetNextVertex(); FibonacciHeap<int, Vertex> labels = state.GetLabelsFibonacciHeap(); HashSet<Vertex> visited = state.GetVisitedHashSet(); Dictionary<Vertex, Path> paths = state.GetPathsFound(); Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node> nodes = state.GetNodeMapping(); Dictionary<Vertex, Edge> comingFrom = state.GetComingFromDictionary(); Dictionary<Vertex, int> components = solution.CreateComponentTable(); Dictionary<Vertex, double> terminalFValues = CreateInitialFValuesTable(graph); int maxLoopsNeeded = graph.Terminals.Count * graph.NumberOfVertices; int loopsDone = 0; int updateInterval = 100; int longestPath = graph.Terminals.Max(x => Algorithms.DijkstraToAll(x, graph).Max(y => y.Value)); while (state.GetLowestLabelVertex() != null) { if (loopsDone % updateInterval == 0) Console.Write("\rRunning IDA... {0:0.0}% \r", 100.0 * loopsDone / maxLoopsNeeded); loopsDone++; if (state.GetLowestLabelVertex() != currentVertex) { // Interleave. Switch to the Dijkstra procedure of the vertex which currently has the lowest distance. state.SetLabelsFibonacciHeap(labels); state.SetVisitedHashSet(visited); state.SetPathsFound(paths); state.SetComingFromDictionary(comingFrom); currentVertex = state.GetNextVertex(); labels = state.GetLabelsFibonacciHeap(); visited = state.GetVisitedHashSet(); paths = state.GetPathsFound(); nodes = state.GetNodeMapping(); comingFrom = state.GetComingFromDictionary(); } // Do one loop in Dijkstra algorithm var currentNode = labels.ExtractMin(); var current = currentNode.Value; if (currentNode.Key > longestPath / 2) break; //Travelled across the half of longest distance. No use in going further. // Consider all edges ending in unvisited neighbours var edges = graph.GetEdgesForVertex(current).Where(x => !visited.Contains(x.Other(current))); // Update labels on the other end foreach (var edge in edges) { if (currentNode.Key + edge.Cost < nodes[edge.Other(current)].Key) { labels.DecreaseKey(nodes[edge.Other(current)], currentNode.Key + edge.Cost); comingFrom[edge.Other(current)] = edge; } } visited.Add(current); if (current != currentVertex) { // Travel back the new path List<Edge> pathEdges = new List<Edge>(); Vertex pathVertex = current; while (pathVertex != currentVertex) { pathEdges.Add(comingFrom[pathVertex]); pathVertex = comingFrom[pathVertex].Other(pathVertex); } pathEdges.Reverse(); Path path = new Path(currentVertex); path.Edges.AddRange(pathEdges); paths[current] = path; } // Find matching endpoints from two different terminals var mutualEnd = state.FindPathsEndingInThisVertex(current); if (mutualEnd.Count() > 1) { var terminals = mutualEnd.Select(x => x.Start).ToList(); // Step 1. Calculate new heuristic function value for this shared point. // f(x) = (Cost^2)/(NumberOfTerminals^3) var f1 = Math.Pow(mutualEnd.Sum(p => p.TotalCost), 2) / Math.Pow(terminals.Count, 3); var f2 = Math.Pow(mutualEnd.Sum(p => p.TotalCost), 1) / Math.Pow(terminals.Count, 2); var f3 = Math.Pow(mutualEnd.Sum(p => p.TotalCost), 3) / Math.Pow(terminals.Count, 2); var terminalsAvgF = terminals.Select(x => terminalFValues[x]).Average(); var terminalsMinF = terminals.Select(x => terminalFValues[x]).Min(); var f = (new[] { f1, f2, f3 }).Max(); Debug.WriteLine("F value: {0}, Fmin: {3} - Connecting terminals: {1} via {2}", f, string.Join(", ", terminals.Select(x => x.VertexName)), current.VertexName, terminalsMinF); // Do not proceed if f > avgF AND working in same component if (terminals.Select(x => components[x]).Distinct().Count() == 1 && f > terminalsMinF) continue; Debug.WriteLine("Proceeding with connection..."); // Step 2. Disconnect terminals in mutual component. foreach (var group in terminals.GroupBy(x => components[x])) { if (group.Count() <= 1) continue; HashSet<Edge> remove = new HashSet<Edge>(); var sameComponentTerminals = group.ToList(); for (int i = 0; i < sameComponentTerminals.Count-1; i++) { for (int j = i+1; j< sameComponentTerminals.Count; j++) { var removePath = Algorithms.DijkstraPath(sameComponentTerminals[i], sameComponentTerminals[j], solution); foreach (var e in removePath.Edges) remove.Add(e); } } foreach (var e in remove) solution.RemoveEdge(e, false); } components = solution.CreateComponentTable(); // Step 3. Reconnect all now disconnected terminals via shared endpoint foreach (var t in terminals) { var path = Algorithms.DijkstraPath(t, current, graph); foreach (var edge in path.Edges) solution.AddEdge(edge); // Update f value terminalFValues[t] = f; } components = solution.CreateComponentTable(); } } // If this solution is connected, take MST if (graph.Terminals.Select(x => components[x]).Distinct().Count() == 1) { // Clean up! foreach (var vertex in solution.Vertices.Where(x => solution.GetDegree(x) == 0).ToList()) solution.RemoveVertex(vertex); int componentNumber = graph.Terminals.Select(x => components[x]).Distinct().Single(); foreach (var vertex in components.Where(x => x.Value != componentNumber).Select(x => x.Key).ToList()) solution.RemoveVertex(vertex); solution = Algorithms.Kruskal(solution); return solution; } // If the solution is not connected, it is not a good solution. return null; }