Beispiel #1
0
        public static Graph RunSolver(Graph graph, Graph tmst)
        {
            HashSet<Edge> redundantEdges = new HashSet<Edge>(graph.Edges);
            foreach (var mstEdge in tmst.Edges)
            {
                var v1 = mstEdge.Either();
                var v2 = mstEdge.Other(v1);
                var path = Algorithms.DijkstraPath(v1, v2, graph);
                foreach (var edge in path.Edges.Where(edge => redundantEdges.Contains(edge)))
                    redundantEdges.Remove(edge);
            }

            var solutionEdge = graph.Clone();
            foreach (var edge in redundantEdges)
                solutionEdge.RemoveEdge(edge);

            // Break cycles in the graph!
            // Solution: Take MST
            // Observation: mostly there are none
            solutionEdge = Algorithms.Kruskal(solutionEdge);
            var TMSTEremoveVertices = new HashSet<Vertex>();
            foreach (var vertex in solutionEdge.Vertices)
            {
                if (solutionEdge.GetDegree(vertex) == 1 && !graph.Terminals.Contains(vertex))
                    TMSTEremoveVertices.Add(vertex);
            }
            foreach (var vertex in TMSTEremoveVertices)
                solutionEdge.RemoveVertex(vertex);

            return solutionEdge;
        }
        public static ReductionResult RunTest(Graph graph)
        {
            var result = new ReductionResult();

            List<int> bottlenecks = new List<int>();
            for (int i = 0; i < graph.Terminals.Count; i++)
            {
                var pathToAll = Algorithms.DijkstraPathToAll(graph.Terminals[i], graph);
                // Only add the maximum bottleneck of all paths
                bottlenecks.Add(pathToAll.SelectMany(x => x.Value.Edges).Max(e => e.Cost));
            }

            int B = bottlenecks.Max();

            List<Edge> redundant = new List<Edge>();
            foreach (var edge in graph.Edges.Where(edge => edge.Cost > B))
                redundant.Add(edge);

            foreach (var edge in redundant)
            {
                graph.RemoveEdge(edge);
                result.RemovedEdges.Add(edge);
            }

            return result;
        }
Beispiel #3
0
        public static ReductionResult RunTest(Graph graph, int upperBound)
        {
            var graphContracted = graph.Clone();
            int reductionBound = int.MaxValue;

            // 1. Contract edges in MST that are in same Voronoi region
            var degreeTwo = graphContracted.Vertices.Where(x => graphContracted.GetDegree(x) == 2).ToList(); // Vertices which could be removed by contracting their adjacent edges
            foreach (var vertex in degreeTwo)
            {
                var voronoi = graph.GetVoronoiRegionForVertex(vertex);
                var edge1 = graphContracted.GetEdgesForVertex(vertex)[0];
                var edge2 = graphContracted.GetEdgesForVertex(vertex)[1];
                var vertex1 = edge1.Other(vertex);
                var vertex2 = edge2.Other(vertex);

                if (graph.GetVoronoiRegionForVertex(vertex1) == voronoi &&
                    graph.GetVoronoiRegionForVertex(vertex2) == voronoi)
                {
                    // Contract the two edges.
                    graphContracted.AddEdge(vertex1, vertex2, edge1.Cost + edge2.Cost);
                    graphContracted.RemoveEdge(edge1);
                    graphContracted.RemoveEdge(edge2);
                }
            }

            var G = new Graph(graph.Terminals);

            var result = new ReductionResult();
            result.ReductionUpperBound = reductionBound;

            return result;
        }
Beispiel #4
0
        /// <summary>
        /// Runs the Degree Test to reduce the graph.
        /// </summary>
        /// <param name="graph">The graph on which to run the test.</param>
        /// <returns>The reduced graph.</returns>
        public static ReductionResult RunTest(Graph graph)
        {
            // Use some simple rules to reduce the problem.
            // The rules are: - if a vertex v has degree 1 and is not part of the required nodes, remove the vertex.
            //                - if a vertex v has degree 1 and is part of the required nodes, the one edge it is
            //                  connected to has to be in the solution, and as a consequence, the node at the other side
            //                  is either a Steiner node or also required.
            //                - (not implemented yet) if a vertex v is required and has degree 2, and thus is connected to 2 edges,
            //                  namely e1 and e2, and cost(e1) < cost(e2) and e1 = (u, v) and u is
            //                  also a required vertex, then every solution must contain e1

            var result = new ReductionResult();

            // Remove leaves as long as there are any
            var leaves = graph.Vertices.Where(v => graph.GetDegree(v) == 1 && !graph.Terminals.Contains(v)).ToList();
            while (leaves.Count > 0)
            {
                foreach (var leaf in leaves)
                    graph.RemoveVertex(leaf);
                result.RemovedVertices.AddRange(leaves);
                leaves = graph.Vertices.Where(v => graph.GetDegree(v) == 1 && !graph.Terminals.Contains(v)).ToList();
            }

            // When a leaf is required, add the node on the other side of its one edge to required nodes
            var requiredLeaves = graph.Vertices.Where(v => graph.GetDegree(v) == 1 && graph.Terminals.Contains(v)).ToList();
            foreach (var requiredLeaf in requiredLeaves)
            {
                // Find the edge this leaf is connected to
                var alsoRequired = graph.GetEdgesForVertex(requiredLeaf).Single().Other(requiredLeaf);
                if (!graph.Terminals.Contains(alsoRequired))
                    graph.RequiredSteinerNodes.Add(alsoRequired);
            }

            return result;
        }
Beispiel #5
0
        public static int Dijkstra(Vertex from, Vertex to, Graph graph)
        {
            HashSet<Vertex> visited = new HashSet<Vertex>();
            Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node> nodes = new Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node>();
            FibonacciHeap<int, Vertex> labels = new FibonacciHeap<int, Vertex>();
            // Initialize labels.
            foreach (var vertex in graph.Vertices)
            {
                var n = labels.Add(vertex == from ? 0 : int.MaxValue, vertex);
                nodes.Add(vertex, n);
            }

            int currentLabel = int.MaxValue;
            while (!visited.Contains(to))
            {
                var currentNode = labels.ExtractMin();
                var current = currentNode.Value;
                currentLabel = currentNode.Key;

                // 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);
                }

                visited.Add(current);
            }

            return currentLabel;
        }
Beispiel #6
0
        private static IEnumerable<List<Edge>> AllTriangles(Graph graph)
        {
            List<Vertex> vertices = new List<Vertex>(graph.Vertices);
            vertices.Sort((x, y) => graph.GetDegree(x).CompareTo(graph.GetDegree(y)));
            vertices.Reverse(); // From highest to lowest
            Dictionary<Vertex, int> index = new Dictionary<Vertex, int>();
            Dictionary<Vertex, List<Vertex>> A = new Dictionary<Vertex, List<Vertex>>();

            for (int i = 0; i < vertices.Count; i++)
            {
                index.Add(vertices[i], i);
                A.Add(graph.Vertices[i], new List<Vertex>());
            }

            foreach (var firstVertex in vertices)
            {
                foreach (var firstEdge in graph.GetEdgesForVertex(firstVertex))
                {
                    var secondVertex = firstEdge.Other(firstVertex);
                    if (index[firstVertex] < index[secondVertex])
                    {
                        foreach (var thirdVertex in A[firstVertex].Intersect(A[secondVertex]))
                        {
                            var secondEdge =
                                graph.GetEdgesForVertex(firstVertex).Single(x => x.Other(firstVertex) == thirdVertex);
                            var thirdEdge =
                                graph.GetEdgesForVertex(secondVertex).Single(x => x.Other(secondVertex) == thirdVertex);
                            yield return new List<Edge>(new [] { firstEdge, secondEdge, thirdEdge });
                        }

                        A[secondVertex].Add(firstVertex);
                    }
                }
            }
        }
Beispiel #7
0
        public static Graph RunTest(Graph graph)
        {
            var enumerator = AllTriangles(graph);

            Console.WriteLine("There are {0} triangles in this graph.", enumerator.Count());
            return graph;
        }
Beispiel #8
0
        public static Graph RunSolver(Graph graph, Graph tmst)
        {
            HashSet<Vertex> redundantVertices = new HashSet<Vertex>(graph.Vertices);
            foreach (var mstEdge in tmst.Edges)
            {
                var v1 = mstEdge.Either();
                var v2 = mstEdge.Other(v1);
                var path = Algorithms.DijkstraPath(v1, v2, graph);
                foreach (var vertex in path.Vertices.Where(vertex => redundantVertices.Contains(vertex)))
                    redundantVertices.Remove(vertex);
            }

            var solutionVertex = graph.Clone();
            foreach (var vertex in redundantVertices)
            {
                solutionVertex.RemoveVertex(vertex);
            }
            solutionVertex = Algorithms.Kruskal(solutionVertex);

            var TMSTVremoveVertices = new HashSet<Vertex>();
            foreach (var vertex in solutionVertex.Vertices)
            {
                if (solutionVertex.GetDegree(vertex) == 1 && !graph.Terminals.Contains(vertex))
                    TMSTVremoveVertices.Add(vertex);
            }
            foreach (var vertex in TMSTVremoveVertices)
                solutionVertex.RemoveVertex(vertex);

            return solutionVertex;
        }
Beispiel #9
0
        public static IEnumerable<IEnumerable<Vertex>> BFS2(Graph graph, List<Vertex> visited)
        {
            List<Vertex> nodes = graph.GetNeighboursForVertex(visited.Last());
            var visitedHash = new HashSet<Vertex>(visited);

            foreach (var node in nodes)
            {
                if (visitedHash.Contains(node))
                    continue;
                //if (node == end)
                {
                    visited.Add(node);
                    yield return visited;
                    visited.RemoveAt(visited.Count - 1);
                    //break;
                }
            }

            foreach (var node in nodes)
            {
                if (visitedHash.Contains(node))
                    continue;
                visited.Add(node);
                foreach (var bfs in BFS2(graph, visited))
                    yield return bfs;
                visited.RemoveAt(visited.Count - 1);
            }
        }
Beispiel #10
0
 public Reducer(Graph instance)
 {
     _instance = instance.Clone();
     _solutionUpperBound = Int32.MaxValue;
     _reductionUpperBound = 0;
     _running = false;
     Status = "Not running.";
 }
Beispiel #11
0
        public Solver(Graph instance)
        {
            _instance = instance.Clone();
            _running = false;
            _bls = new BLS();

            _edgesToRemove = new ConcurrentQueue<Edge>();
            _verticesToRemove = new ConcurrentQueue<Vertex>();
        }
Beispiel #12
0
        public static Path DijkstraPath(Vertex from, Vertex to, Graph graph)
        {
            HashSet<Vertex> visited = new HashSet<Vertex>();
            Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node> nodes =
                new Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node>();
            Dictionary<Vertex, Edge> comingFrom = new Dictionary<Vertex, Edge>();
            FibonacciHeap<int, Vertex> labels = new FibonacciHeap<int, Vertex>();
            // Initialize labels.
            foreach (var vertex in graph.Vertices)
            {
                var n = labels.Add(vertex == from ? 0 : int.MaxValue, vertex);
                nodes.Add(vertex, n);
                comingFrom.Add(vertex, null);
            }

            while (!visited.Contains(to))
            {
                var currentNode = labels.ExtractMin();
                var current = currentNode.Value;

                // 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);
            }

            // Now travel back, to find the actual path
            List<Edge> pathEdges = new List<Edge>();
            Vertex pathVertex = to;
            while (pathVertex != from)
            {
                pathEdges.Add(comingFrom[pathVertex]);
                pathVertex = comingFrom[pathVertex].Other(pathVertex);
            }

            pathEdges.Reverse();
            Path path = new Path(from);
            path.Edges.AddRange(pathEdges);
            return path;
        }
Beispiel #13
0
        public static ReductionResult RunTest(Graph graph)
        {
            var result = new ReductionResult();

            var mst = Algorithms.Kruskal(graph.TerminalDistanceGraph);
            var S = mst.Edges.Max(edge => edge.Cost);
            foreach (var edge in graph.Edges.Where(e => e.Cost > S).ToList())
            {
                graph.RemoveEdge(edge);
                result.RemovedEdges.Add(edge);
            }

            return result;
        }
Beispiel #14
0
        public static ReductionResult RunTest(Graph graph, int upperBound)
        {
            var result = new ReductionResult();
            int reductionBound = 0;

            // Given an upper bound for a solution to the Steiner Tree Problem in graphs,
            // a vertex i can be removed if max{distance(i, k)} > upper bound (with k a terminal).
            HashSet<Vertex> remove = new HashSet<Vertex>();
            Dictionary<Vertex, int> currentMaximums = graph.Vertices.ToDictionary(vertex => vertex, vertex => 0);

            foreach (var terminal in graph.Terminals)
            {
                var toAll = Algorithms.DijkstraToAll(terminal, graph);
                foreach (var vertex in graph.Vertices)
                {
                    if (vertex == terminal) continue;
                    if (toAll[vertex] > currentMaximums[vertex])
                        currentMaximums[vertex] = toAll[vertex];
                }
            }

            foreach (var vertex in graph.Vertices)
            {
                if (currentMaximums[vertex] > upperBound)
                    remove.Add(vertex);
                else if (currentMaximums[vertex] > reductionBound)
                    reductionBound = currentMaximums[vertex];
            }

            foreach (var vertex in remove)
            {
                graph.RemoveVertex(vertex);
                result.RemovedVertices.Add(vertex);
            }

            result.ReductionUpperBound = reductionBound;

            return result;
        }
Beispiel #15
0
        public Graph RemoveVertexAndReconnect(Graph currentSolution, Graph problemInstance, Vertex remove)
        {
            var workingSolution = currentSolution.Clone();
            foreach (var vertex in problemInstance.Vertices)
                if (!workingSolution.ContainsVertex(vertex))
                    workingSolution.AddVertex(vertex);

            foreach (var edge in workingSolution.GetEdgesForVertex(remove).ToList())
                workingSolution.RemoveEdge(edge);

            IEnumerable<Vertex> degreeOne;
            while ((degreeOne =
                    workingSolution.Vertices.Except(problemInstance.Terminals)
                        .Where(x => workingSolution.GetDegree(x) == 1)).Any())
            {
                foreach (var degreeZeroSteiner in degreeOne.ToList())
                    foreach (var edge in workingSolution.GetEdgesForVertex(degreeZeroSteiner).ToList())
                        workingSolution.RemoveEdge(edge, false);
            }

            ReconnectTerminals(workingSolution, problemInstance);

            return workingSolution;
        }
        /// <summary>
        /// Runs an approximation of the Special Distance Test to reduce the graph.
        /// This test runs much faster and offers only a small difference in performance.
        /// </summary>
        /// <param name="graph">The graph on which to run the test.</param>
        /// <returns>The reduced graph.</returns>
        public static ReductionResult RunTest(Graph graph)
        {
            if (!graph.Terminals.All(graph.ContainsVertex))
                Debugger.Break();

            var tmst = Algorithms.Kruskal(graph.TerminalDistanceGraph);
            var terminalSpecialDistances = new MultiDictionary<Vertex, int>();
            for (int i = 0; i < graph.Terminals.Count - 1; i++)
            {
                var tFrom = graph.Terminals[i];
                var toAll = Algorithms.DijkstraPathToAll(tFrom, tmst);
                for (int j = i + 1; j < graph.Terminals.Count; j++)
                {
                    var tTo = graph.Terminals[j];
                    var path = toAll[tTo];
                    var sd = path.Edges.Max(x => x.Cost);
                    terminalSpecialDistances.Add(tFrom, tTo, sd);
                }
            }

            var result = new ReductionResult();

            // Find all special distances between terminals
            int count = 0;
            int e = graph.NumberOfEdges;

            Dictionary<Vertex, Path> nearest = new Dictionary<Vertex, Path>();
            HashSet<Edge> remove = new HashSet<Edge>();

            int edgesWithoutRemoval = 0;

            foreach (var edge in graph.Edges.OrderByDescending(x => x.Cost))
            {
                count++;
                var vFrom = edge.Either();
                var vTo = edge.Other(vFrom);

                int SDEstimate = int.MaxValue;
                Path pathToNearestFrom = null;
                if (nearest.ContainsKey(vFrom))
                    pathToNearestFrom = nearest[vFrom];
                else
                {
                    pathToNearestFrom = Algorithms.NearestTerminal(vFrom, graph);
                    nearest.Add(vFrom, pathToNearestFrom);
                }
                var aNearestTerminalFrom = pathToNearestFrom.End;

                Path pathToNearestTo = null;
                if (nearest.ContainsKey(vTo))
                    pathToNearestTo = nearest[vTo];
                else
                {
                    pathToNearestTo = Algorithms.NearestTerminal(vTo, graph);
                    nearest.Add(vTo, pathToNearestTo);
                }
                var bNearestTerminalTo = pathToNearestTo.End;

                // SD = Max( dist(v, z_a), dist(w, z_b), sd(z_a, z_b) )
                var sd = Math.Max(pathToNearestFrom.TotalCost, pathToNearestTo.TotalCost);
                if (aNearestTerminalFrom != bNearestTerminalTo)
                {
                    var sdTerminals = terminalSpecialDistances[aNearestTerminalFrom, bNearestTerminalTo];
                    sd = Math.Max(sd, sdTerminals);
                }

                if (sd < SDEstimate)
                    SDEstimate = sd;

                if (edge.Cost > SDEstimate)
                {
                    edgesWithoutRemoval = 0;
                    remove.Add(edge);
                }
                else if (++edgesWithoutRemoval >= graph.NumberOfEdges / 100) // Expecting a 1% reduction
                {
                    break;
                }
            }

            foreach (var edge in remove)
            {
                graph.RemoveEdge(edge);
                result.RemovedEdges.Add(edge);
            }

            return result;
        }
Beispiel #17
0
 /// <summary>
 /// Method to create and return a complete graph (like a distance graph), but
 /// each edge has cost int.MaxValue. Those costs are later changed to be the
 /// special distances between vertices.
 /// </summary>
 /// <param name="graph">The graph to calculate the initial special distance graph for.</param>
 /// <returns>The initial special distance graph, containing all int.MaxValue special distances.</returns>
 private static Graph CreateInitialSpecialDistanceGraph(Graph graph)
 {
     var n = graph.NumberOfVertices;
     Graph specialGraph = new Graph(graph.Vertices);
     for (int from = 0; from < n; from++)
     {
         for (int to = from + 1; to < n; to++)
         {
             var vFrom = graph.Vertices[from];
             var vTo = graph.Vertices[to];
             specialGraph.AddEdge(vFrom, vTo, int.MaxValue);
         }
     }
     return specialGraph;
 }
Beispiel #18
0
        /// <summary>
        /// Runs the Special Distance Test to reduce the graph.
        /// </summary>
        /// <param name="graph">The graph on which to run the test.</param>
        /// <returns>The reduced graph.</returns>
        public static ReductionResult RunTest(Graph graph)
        {
            List<Edge> redundant = new List<Edge>();
            var result = new ReductionResult();

            var distanceGraph = graph.CreateDistanceGraph();
            var specialDistanceGraph = CreateInitialSpecialDistanceGraph(graph);
            for (int i = 0; i < graph.NumberOfVertices; i++)
            {
                Console.Write("SD Test: {0}/{1}   \r", i, graph.NumberOfVertices);
                // Step 1. L := { i }
                //         for all j set delta_j = d_ij
                // In each iteration, delta_j means the current special distance from the start vertex to j.
                var vFrom = graph.Vertices[i];
                List<Vertex> L = new List<Vertex>(new [] { vFrom }); // Initially only the start veretx is labeled.
                // Initially set special distance equal to distance
                foreach (var edge in specialDistanceGraph.GetEdgesForVertex(vFrom))
                {
                    edge.Cost =
                        distanceGraph.GetEdgesForVertex(vFrom).Single(x => x.Other(vFrom) == edge.Other(vFrom)).Cost;
                    //edge.Cost = Math.Min(edge.Cost,
                    //    distanceGraph.GetEdgesForVertex(vFrom).Single(x => x.Other(vFrom) == edge.Other(vFrom)).Cost);
                }

                List<Vertex> unhandledTerminals = null; // K \ L
                while ((unhandledTerminals = graph.Terminals.Where(x => !L.Contains(x)).ToList()).Count > 0)
                { // While K \ L is not empty
                    // Find the terminal which minimizes delta(j) for all j in K \ L
                    int currentMinimum = int.MaxValue;
                    Vertex k = null;
                    var edgesFrom = specialDistanceGraph.GetEdgesForVertex(vFrom);
                    foreach (var terminal in unhandledTerminals)
                    {
                        var deltaEdge = edgesFrom.First(x => x.Other(vFrom) == terminal);
                        if (deltaEdge.Cost < currentMinimum)
                        {
                            currentMinimum = deltaEdge.Cost;
                            k = terminal;
                        }
                    }

                    L.Add(k);

                    // Re-lable all vertices that haven't gotten a definitive label yet.
                    var delta_k = edgesFrom.First(x => x.Other(vFrom) == k).Cost;
                    foreach (var unlabeled in graph.Vertices.Where(x => !L.Contains(x)))
                    {
                        var d_kj = distanceGraph.GetEdgesForVertex(k).First(x => x.Other(k) == unlabeled).Cost;
                        var deltaEdge = edgesFrom.First(x => x.Other(vFrom) == unlabeled);
                        deltaEdge.Cost = Math.Min(deltaEdge.Cost, Math.Max(delta_k, d_kj));
                    }
                }

                var specialEdges = specialDistanceGraph.GetEdgesForVertex(vFrom);
                var distanceEdges = distanceGraph.GetEdgesForVertex(vFrom);
                var edges = graph.GetEdgesForVertex(vFrom);
                foreach (var redundantEdge in specialEdges.Where(x => x.Cost < distanceEdges.First(y => y.Other(vFrom) == x.Other(vFrom)).Cost))
                {
                    // Special distance is smaller than distance. Edge is redundant.
                    var edge = edges.FirstOrDefault(x => x.Other(vFrom) == redundantEdge.Other(vFrom));
                    if (edge != null)
                        redundant.Add(edge);
                }
            }

            foreach (var edge in redundant)
            {
                graph.RemoveEdge(edge);
                result.RemovedEdges.Add(edge);
            }

            Console.Write("                                  \r");

            return result;
        }
Beispiel #19
0
        private void AddEdgesToMST(Graph mst, List<Edge> edges)
        {
            foreach (var edge in edges)
            {
                if (edge.WhereBoth(x => mst.GetDegree(x) > 0)) //Both vertices of this edge are in the MST, introducing this edge creates cycle!
                {
                    var v1 = edge.Either();
                    var v2 = edge.Other(v1);
                    var components = mst.CreateComponentTable();

                    if (components[v1] == components[v2])
                    {
                        // Both are in the same component, and a path exists.
                        // Travel the path to see if adding this edge makes it cheaper
                        var path = Algorithms.DijkstraPath(v1, v2, mst);

                        // However, we can remove a set of edges between two nodes
                        // When going from T1 to T3
                        // E.g.: T1 - v2 - v3 - v4 - T2 - v5 - v6 - T3
                        // The edges between T1, v2, v3, v4, T2 cost more than the path between T1 and T3.
                        // Removing those edges, and adding the new edge from T1 to T3, also connects
                        // T1 to T2, so still a tree!
                        var from = path.Start;
                        var last = path.Start;
                        int betweenTerminals = 0;
                        var subtractedPath = new Path(path.Start);
                        List<Edge> edgesInSubtraction = new List<Edge>();
                        Dictionary<Edge, List<Edge>> subtractions = new Dictionary<Edge, List<Edge>>();
                        for (int i = 0; i < path.Edges.Count; i++)
                        {
                            var pe = path.Edges[i];
                            betweenTerminals += pe.Cost;
                            last = pe.Other(last);
                            edgesInSubtraction.Add(pe);
                            if (mst.GetDegree(last) > 2 || mst.Terminals.Contains(last) || i == path.Edges.Count - 1)
                            {
                                var subtractedEdge = new Edge(from, last, betweenTerminals);
                                subtractions.Add(subtractedEdge, edgesInSubtraction);
                                edgesInSubtraction = new List<Edge>();
                                subtractedPath.Edges.Add(subtractedEdge);
                                from = last;
                                betweenTerminals = 0;
                            }
                        }

                        var mostCostly = subtractedPath.Edges[0];
                        for (int i = 1; i < subtractedPath.Edges.Count; i++)
                        {
                            if (subtractedPath.Edges[i].Cost > mostCostly.Cost)
                                mostCostly = subtractedPath.Edges[i];
                        }

                        if (mostCostly.Cost >= edge.Cost)
                        {
                            foreach (var e in subtractions[mostCostly])
                                mst.RemoveEdge(e, false);
                            mst.AddEdge(edge);
                        }
                    }
                    else // Connect the two disconnected components!
                        mst.AddEdge(edge);
                }
                else
                    mst.AddEdge(edge);
            }
        }
Beispiel #20
0
        /// <summary>
        /// Creates a distance graph for this graph.
        /// Subtle note: the terminals used for this graph are the terminals for the problem,
        /// and the nodes that are considered required Steiner nodes.
        /// </summary>
        /// <returns></returns>
        private Graph CreateTerminalDistanceGraph()
        {
            var terminals = this.Required.ToList();
            var n = terminals.Count;
            var edgesCalculated = 0;
            var edgesToCalculate = (n * (n - 1)) / 2;
            int beforeUpdate = (edgesToCalculate / 200) + 1;
            Graph distanceGraph = new Graph(terminals);

            for (int from = 0; from < n; from++)
            {
                var vFrom = terminals[from];
                var distanceToAll = Algorithms.DijkstraToAll(vFrom, this);
                foreach (var dist in distanceToAll)
                {
                    var vTo = dist.Key;
                    if (vTo.VertexName > vFrom.VertexName || !terminals.Contains(vTo))
                        continue;

                    distanceGraph.AddEdge(vFrom, vTo, dist.Value);
                    edgesCalculated++;
                }
            }

            return distanceGraph;
        }
Beispiel #21
0
        /// <summary>
        /// Creates an exact copy of this graph.
        /// </summary>
        /// <returns></returns>
        public Graph Clone()
        {
            Graph clone = new Graph(Vertices);
            foreach (var edge in GetAllEdges())
                clone.AddEdge(edge);
            foreach (var terminal in Terminals)
                clone.Terminals.Add(terminal);
            foreach (var requiredSteinerNode in RequiredSteinerNodes)
                clone.RequiredSteinerNodes.Add(requiredSteinerNode);
            clone._terminalDistance = _terminalDistance;

            return clone;
        }
Beispiel #22
0
        private static Graph ParseORBenchmark(string path)
        {
            Graph g;

            using (StreamReader sr = new StreamReader(File.Open(path, FileMode.Open)))
            {
                // Read the number of edges and vertices
                string metadata = sr.ReadLine().RemoveWhitespace();
                int nbEdges = int.Parse(metadata.Split(' ')[1]);
                int nbVertices = int.Parse(metadata.Split(' ')[0]);
                g = new Graph(nbVertices);

                // Read all edges and add them to the graph
                for (int i = 0; i < nbEdges; i++)
                {
                    string rawline = sr.ReadLine().RemoveWhitespace();
                    int start = int.Parse(rawline.Split(' ')[0]);
                    int end = int.Parse(rawline.Split(' ')[1]);
                    int cost = int.Parse(rawline.Split(' ')[2]);

                    g.AddEdge(g.Vertices.Single(x => x.VertexName == start), g.Vertices.Single(x => x.VertexName == end), cost);
                }

                // Read the Steiner nodes and save them
                int numberOfRequiredNodes = int.Parse(sr.ReadLine().RemoveWhitespace());
                IEnumerable<Vertex> requiredNodes = sr.ReadLine().RemoveWhitespace().Split(' ').Where(x => x.Length > 0).Select(x => g.Vertices.Single(v => v.VertexName == int.Parse(x)));
                g.Terminals.AddRange(requiredNodes);
            }

            return g;
        }
Beispiel #23
0
        private static Graph ParseSteinLibBenchmark(string path)
        {
            Graph g = null;

            using (StreamReader sr = new StreamReader(File.Open(path, FileMode.Open)))
            {
                string line;

                int nodes;
                int edges;
                while ((line = sr.ReadLine()) != null)
                {
                    if (line.Equals("SECTION Graph", StringComparison.InvariantCultureIgnoreCase))
                    {
                        nodes = int.Parse(sr.ReadLine().Split(' ')[1]);
                        edges = int.Parse(sr.ReadLine().Split(' ')[1]);
                        List<Vertex> vertices = new List<Vertex>();
                        for (int i = 0; i < nodes; i++)
                            vertices.Add(new Vertex(i+1));

                        g = new Graph(vertices);

                        for (int i = 0; i < edges; i++)
                        {
                            string gline = sr.ReadLine();
                            if (gline == null || gline.Trim().Length == 0)
                                continue;

                            string[] edgeData = gline.Split(' ');
                            int from = int.Parse(edgeData[1]);
                            int to = int.Parse(edgeData[2]);
                            int cost = int.Parse(edgeData[3]);
                            g.AddEdge(vertices[from-1], vertices[to-1], cost);
                        }

                    }
                    else if (line.Equals("SECTION Terminals", StringComparison.InvariantCultureIgnoreCase))
                    {
                        int terminals = int.Parse(sr.ReadLine().Split(' ')[1]);
                        for (int i = 0; i < terminals; i++)
                        {
                            int terminalNumber = int.Parse(sr.ReadLine().Split(' ')[1]);
                            var t = g.Vertices.Single(x => x.VertexName == terminalNumber);
                            g.Terminals.Add(t);
                        }
                    }
                }
            }

            return g;
        }
Beispiel #24
0
        /// <summary>
        /// Method to remove a vertex from this graph. 
        /// Also removes all the edges that this vertex was connected to.
        /// </summary>
        /// <param name="vertex">The vertex to remove.</param>
        public void RemoveVertex(Vertex vertex)
        {
            if (!_vertices.Contains(vertex))
                return;
            _vertices.Remove(vertex);
            Vertices.Remove(vertex);
            foreach (var edge in _adjacencies[vertex].ToList())
                RemoveEdge(edge);

            _terminalDistance = null;
            _adjacencies.Remove(vertex);
        }
Beispiel #25
0
        /// <summary>
        /// Method to remove an edge from the graph.
        /// </summary>
        /// <param name="edge">The edge to be removed.</param>
        /// <param name="removeDegreeZero">Indicates whether when a vertex becomes of degree zero, it should be removed. Default: True.</param>
        public void RemoveEdge(Edge edge, bool removeDegreeZero = true)
        {
            var v1 = edge.Either();
            var v2 = edge.Other(v1);
            _adjacencies[v1].Remove(edge);
            _adjacencies[v2].Remove(edge);

            if (removeDegreeZero)
            {
                if (GetDegree(v1) == 0)
                    RemoveVertex(v1);
                if (GetDegree(v2) == 0)
                    RemoveVertex(v2);
            }

            _edgesUpToDate = false;
            _terminalDistance = null;
            _voronoiRegions.Clear();
        }
Beispiel #26
0
        public void AddEdge(Edge edge)
        {
            var from = edge.Either();
            var to = edge.Other(from);
            if (!_adjacencies.ContainsKey(from) || !_adjacencies.ContainsKey(to))
                throw new ArgumentException("This edge can not be added as it connects vertices that are not in the graph.");

            _adjacencies[from].Add(edge);
            _adjacencies[to].Add(edge);
            _edgesUpToDate = false;
            _terminalDistance = null;
        }
Beispiel #27
0
        public static ReductionResult RunTest(Graph graph, int upperBound)
        {
            var result = new ReductionResult();

            // T. Polzin, lemma 25: Vertex removal
            int reductionBound = 0;
            int allRadiusesExceptTwoMostExpensive = graph.Terminals.Select(graph.GetVoronoiRadiusForTerminal).OrderBy(x => x).Take(graph.Terminals.Count - 2).Sum();
            HashSet<Vertex> removeVertices = new HashSet<Vertex>();
            foreach (var vertex in graph.Vertices.Except(graph.Required))
            {
                var nearestTerminals = Algorithms.NearestTerminals(vertex, graph, 2);
                int lowerBound = nearestTerminals.Sum(x => x.TotalCost) + allRadiusesExceptTwoMostExpensive;

                if (lowerBound > upperBound)
                    removeVertices.Add(vertex);
                else if (lowerBound > reductionBound)
                    reductionBound = lowerBound;
            }

            foreach (var removeVertex in removeVertices)
            {
                graph.RemoveVertex(removeVertex);
                result.RemovedVertices.Add(removeVertex);
            }

            // Check for disconnected components (and remove those that not contain any terminals)
            var componentTable = graph.CreateComponentTable();
            var terminalComponents = new HashSet<int>();
            foreach (var vertex in graph.Terminals)
                terminalComponents.Add(componentTable[vertex]);

            foreach (var vertex in graph.Vertices.Where(x => !terminalComponents.Contains(componentTable[x])).ToList())
            {
                graph.RemoveVertex(vertex);
                result.RemovedVertices.Add(vertex);
            }

            // T. Polzin, lemma 26: edge removal
            allRadiusesExceptTwoMostExpensive = graph.Terminals.Select(graph.GetVoronoiRadiusForTerminal).OrderBy(x => x).Take(graph.Terminals.Count - 2).Sum();
            HashSet<Edge> removeEdges = new HashSet<Edge>();
            Dictionary<Vertex, int> distancesToBase = new Dictionary<Vertex, int>();
            foreach (var terminal in graph.Terminals)
            {
                var toAll = Algorithms.DijkstraToAll(terminal, graph);
                foreach (var vertex in graph.Vertices)
                {
                    if (vertex == terminal)
                        continue;

                    if (!distancesToBase.ContainsKey(vertex))
                        distancesToBase.Add(vertex, toAll[vertex]);
                    else if (toAll[vertex] < distancesToBase[vertex])
                        distancesToBase[vertex] = toAll[vertex];
                }
            }

            foreach (var edge in graph.Edges)
            {
                var v1 = edge.Either();
                var v2 = edge.Other(v1);

                if (graph.Terminals.Contains(v1) || graph.Terminals.Contains(v2))
                    continue;

                var v1z1 = distancesToBase[v1];
                var v2z2 = distancesToBase[v2];
                var lowerBound = edge.Cost + v1z1 + v2z2 + allRadiusesExceptTwoMostExpensive;

                if (lowerBound > upperBound)
                    removeEdges.Add(edge);
                else if (lowerBound > reductionBound)
                    reductionBound = lowerBound;
            }

            foreach (var removeEdge in removeEdges)
            {
                graph.RemoveEdge(removeEdge);
                result.RemovedEdges.Add(removeEdge);
            }

            result.ReductionUpperBound = reductionBound;
            return result;
        }
Beispiel #28
0
        private void ReconnectTerminals(Graph workingSolution, Graph problemInstance, Graph problemInstanceDistance)
        {
            Stopwatch reconnectStopwatch = new Stopwatch();
            reconnectStopwatch.Start();

            var components = workingSolution.CreateComponentTable();
            var componentsToConnect =
                components.Where(x => problemInstance.Terminals.Contains(x.Key))
                    .Select(x => x.Value)
                    .Distinct()
                    .ToList();

            if (componentsToConnect.Count <= 1) return;

            MultiDictionary<int, Tuple<Vertex, Vertex>> componentConnectingPathDictionary = new MultiDictionary<int, Tuple<Vertex, Vertex>>();
            List<Vertex> componentGraphVertices = new List<Vertex>();
            foreach (var i in componentsToConnect)
                componentGraphVertices.Add(new Vertex(i));
            Graph componentGraph = new Graph(componentGraphVertices);

            for (int i = 0; i < componentsToConnect.Count; i++)
            {
                int fromComponent = componentsToConnect[i];
                for (int j = i + 1; j < componentsToConnect.Count; j++)
                {
                    int toComponent = componentsToConnect[j];
                    int minDistance = int.MaxValue;

                    foreach (var fromVertex in components.Where(x => x.Value == fromComponent)
                                                         .Select(x => x.Key))
                    {
                        var distanceEdges = problemInstanceDistance.GetEdgesForVertex(fromVertex);
                        foreach (var toVertexEdge in distanceEdges)
                        {
                            var toVertex = toVertexEdge.Other(fromVertex);
                            if (components[toVertex] != toComponent)
                                continue;

                            int distance = toVertexEdge.Cost;
                            if (!componentConnectingPathDictionary.ContainsKey(fromComponent, toComponent))
                            {
                                componentConnectingPathDictionary.Add(fromComponent, toComponent, new Tuple<Vertex, Vertex>(fromVertex, toVertex));
                                componentGraph.AddEdge(new Edge(componentGraphVertices[i], componentGraphVertices[j], minDistance));
                            }

                            if (distance < minDistance)
                            {
                                minDistance = distance;
                                componentConnectingPathDictionary[fromComponent, toComponent] = new Tuple<Vertex, Vertex>(fromVertex, toVertex);
                                componentGraph.GetEdgesForVertex(componentGraphVertices[i])
                                    .Single(x => x.Other(componentGraphVertices[i]) == componentGraphVertices[j])
                                    .Cost = minDistance;
                            }
                        }
                    }
                }
            }
            componentGraph = Algorithms.Kruskal(componentGraph);
            foreach (var edge in componentGraph.Edges)
            {
                var v1 = edge.Either();
                var v2 = edge.Other(v1);
                var vertices = componentConnectingPathDictionary[v1.VertexName, v2.VertexName];
                var path = Algorithms.DijkstraPath(vertices.Item1, vertices.Item2, problemInstance);
                foreach (var pathEdge in path.Edges)
                    workingSolution.AddEdge(pathEdge);
            }

            reconnectStopwatch.Stop();
        }
Beispiel #29
0
        /// <summary>
        /// Method to create and return the distance graph of this graph.
        /// </summary>
        /// <returns>The distance graph of the current instance of the graph.</returns>
        public Graph CreateDistanceGraph()
        {
            var n = this.NumberOfVertices;
            Graph distanceGraph = new Graph(Vertices);
            for (int from = 0; from < n; from++)
            {
                var vFrom = Vertices[from];
                var distanceToAll = Algorithms.DijkstraToAll(vFrom, this);
                foreach (var dist in distanceToAll)
                {
                    var vTo = dist.Key;
                    if (vTo.VertexName > vFrom.VertexName)
                        continue;
                    distanceGraph.AddEdge(vFrom, vTo, dist.Value);
                }
            }

            return distanceGraph;
        }
Beispiel #30
0
        public void AddVertex(Vertex vertex)
        {
            if (_vertices.Contains(vertex))
                return;

            Vertices.Add(vertex);
            _vertices.Add(vertex);
            _adjacencies.Add(vertex, new List<Edge>());
            _terminalDistance = null;
        }