Esempio n. 1
0
 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;
         }
     }
 }
Esempio n. 2
0
    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;
        }