Пример #1
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;
        }
Пример #2
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;
        }
Пример #3
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;
        }
Пример #4
0
 public Reducer(Graph instance)
 {
     _instance = instance.Clone();
     _solutionUpperBound = Int32.MaxValue;
     _reductionUpperBound = 0;
     _running = false;
     Status = "Not running.";
 }
Пример #5
0
        public Solver(Graph instance)
        {
            _instance = instance.Clone();
            _running = false;
            _bls = new BLS();

            _edgesToRemove = new ConcurrentQueue<Edge>();
            _verticesToRemove = new ConcurrentQueue<Vertex>();
        }
Пример #6
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;
        }
Пример #7
0
        private static Graph KruskalB(Graph graph)
        {
            HashSet<Vertex> inTree = new HashSet<Vertex>();
            Graph mst = graph.Clone();
            foreach (var edge in mst.Edges)
                mst.RemoveEdge(edge);

            // Start with one random vertex
            inTree.Add(graph.Vertices[0]);
            while (mst.NumberOfEdges < graph.NumberOfVertices - 1)
            {
                // Find new edge to add to the tree.
                var candidateEdges = inTree.SelectMany(graph.GetEdgesForVertex).ToList();
                candidateEdges.Sort((x, y) => x.Cost.CompareTo(y.Cost)); // Sort from cheap to expensive
                foreach (var edge in candidateEdges)
                {
                    var v1 = edge.Either();
                    var v2 = edge.Other(v1);
                    bool v1InTree = inTree.Contains(v1);
                    bool v2InTree = inTree.Contains(v2);
                    if (v1InTree ^ v2InTree) // The ^ is a XOR
                    {
                        // One side of this edge is in the MST, the other is not
                        mst.AddEdge(edge);
                        inTree.Add(v1);
                        inTree.Add(v2);
                        break;
                    }
                }
            }

            return mst;
        }
Пример #8
0
        private static Graph KruskalA(Graph graph)
        {
            HashSet<Vertex> inTree = new HashSet<Vertex>();
            Graph mst = graph.Clone();
            foreach (var edge in mst.Edges)
                mst.RemoveEdge(edge, false);

            Dictionary<Vertex, int> components = new Dictionary<Vertex, int>();
            for(int i = 0; i < graph.Vertices.Count; i++)
                components.Add(graph.Vertices[i], i);

            // Start with cheapest edge!
            var edges = graph.Edges.ToList();
            edges.Sort((x, y) => x.Cost.CompareTo(y.Cost));
            var startEdge = edges[0];
            inTree.Add(startEdge.Either());
            inTree.Add(startEdge.Other(startEdge.Either()));
            mst.AddEdge(startEdge);
            components[startEdge.Either()] = components[startEdge.Other(startEdge.Either())];
            edges.RemoveAt(0);

            while (mst.NumberOfEdges < graph.NumberOfVertices - 1)
            {
                // Take the first edge that does not introduce a cycle, thus connects 2 components
                Edge edge = null;
                do
                {
                    edge = edges[0];
                    edges.RemoveAt(0);
                } while (components[edge.Either()] == components[edge.Other(edge.Either())]);

                var v1 = edge.Either();
                var v2 = edge.Other(v1);
                inTree.Add(v1);
                inTree.Add(v2);
                mst.AddEdge(edge);

                // Merge the components
                int c1 = components[v1];
                int c2 = components[v2];
                foreach (var component in components.Where(x => x.Value == c2).ToList())
                {
                    components[component.Key] = c1;
                }
            }

            return mst;
        }
Пример #9
0
        public static Graph RunSolver(Graph graph)
        {
            GRBEnv env = new GRBEnv();
            env.Set(GRB.IntParam.OutputFlag, 0);
            env.Set(GRB.IntParam.LogToConsole, 0);
            env.Set(GRB.IntParam.Presolve, 2);
            env.Set(GRB.DoubleParam.Heuristics, 0.0);
            GRBModel model = new GRBModel(env);
            GRBVar[] variables = new GRBVar[graph.NumberOfEdges];
            model.SetCallback(new LPSolverCallback());
            Dictionary<Edge, GRBVar> edgeVars = new Dictionary<Edge, GRBVar>();

            // Add variables to the LP model
            for (int i = 0; i < graph.NumberOfEdges; i++)
            {
                variables[i] = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, "x_" + i);
                edgeVars.Add(graph.Edges[i], variables[i]);
            }
            model.Update();

            // Add constraints to the LP model
            Console.Write("\rRunning LP. Creating constraints...\r");
            //var nonTerminals = graph.Vertices.Except(graph.Terminals).ToList();
            ulong conNr = 0;
            //var terminalCombinations = new List<List<Vertex>>();

            // Assume, without loss of generality, that Terminals[0] is the root, and thus is always included
            int rootNr = 1;
            foreach (var rootTerminal in graph.Terminals)
            //var rootTerminal = graph.Terminals[0];
            {
                Console.Write("\rRunning LP. Creating constraints... {0}/{1}\r", rootNr, graph.Terminals.Count);
                foreach (var combination in GetBFS(graph, rootTerminal))
                {
                    var nodes = combination.ToList(); //new HashSet<Vertex>(combination);
                    if (nodes.Count == graph.NumberOfVertices || graph.Terminals.All(nodes.Contains))
                        continue;
                    //Debug.WriteLine("Combination: {0}", string.Join(" ", nodes));
                    //for (int i = 1; i <= nodes.Count; i++)
                    {
                        var edges = nodes//.Take(i)
                                         .SelectMany(graph.GetEdgesForVertex)
                                         .Distinct()
                                         .Where(x => x.WhereOne(y => !nodes.Contains(y)));
                        GRBLinExpr expression = 0;
                        foreach (var edge in edges)
                            expression.AddTerm(1, edgeVars[edge]);
                        model.AddConstr(expression >= 1.0, "subset_" + conNr);
                        conNr++;

                        if (conNr % 100000 == 0)
                        {
                            //model = model.Presolve(); //Pre-solve the model every 1000 constraints.
                            int constrBefore = model.GetConstrs().Length, varsBefore = model.GetVars().Length;
                            Debug.WriteLine("Presolve called.");
                            var presolved = model.Presolve();
                            Debug.WriteLine("Model has {0} constraints, {1} variables. Presolve has {2} constraints, {3} variables",
                                constrBefore, varsBefore, presolved.GetConstrs().Length, presolved.GetVars().Length);
                        }
                    }
                }

                //Debug.WriteLine("   ");
                //Debug.WriteLine("   ");
                rootNr++;
            }

            //terminalCombinations.Add(new List<Vertex>(new[] { graph.Terminals[0] }));
            //for (int j = 1; j < graph.Terminals.Count - 1; j++)
            //    terminalCombinations.AddRange(new Combinations<Vertex>(graph.Terminals.Skip(1), j).Select(combination => combination.Union(new[] { graph.Terminals[0] }).ToList()));

            //long nonTerminalSetsDone = 0;
            //long nonTerminalSets = 0;
            //for (int i = 0; i <= nonTerminals.Count; i++)
            //    nonTerminalSets += Combinations<Vertex>.NumberOfCombinations(nonTerminals.Count, i);

            //for (int i = 0; i <= nonTerminals.Count; i++)
            //{
            //    foreach (var nonTerminalSet in new Combinations<Vertex>(nonTerminals, i))
            //    {
            //        foreach (var nodes in (from a in terminalCombinations
            //                               select new HashSet<Vertex>(a.Union(nonTerminalSet))))
            //        {
            //            var edges = nodes.SelectMany(graph.GetEdgesForVertex)
            //                             .Distinct()
            //                             .Where(x => x.WhereOne(y => !nodes.Contains(y)));
            //            GRBLinExpr expression = 0;
            //            foreach (var edge in edges)
            //                expression.AddTerm(1, edgeVars[edge]);
            //            model.AddConstr(expression >= 1.0, "subset_" + conNr);
            //            conNr++;
            //        }
            //        nonTerminalSetsDone++;
            //        if (nonTerminalSetsDone % 100 == 0)
            //            Console.Write("\rRunning LP. Creating constraints... {0}/{1} ({2:0.000}%)\r", nonTerminalSetsDone, nonTerminalSets, nonTerminalSetsDone * 100.0 / nonTerminalSets);
            //    }
            //}

            // Solve the LP model
            Console.Write("\rRunning LP. Creating objective & updating...                                   \r");
            GRBLinExpr objective = new GRBLinExpr();
            for (int i = 0; i < graph.NumberOfEdges; i++)
                objective.AddTerm(graph.Edges[i].Cost, variables[i]);
            model.SetObjective(objective, GRB.MINIMIZE);
            Console.Write("\rRunning LP. Tuning...                                   \r");
            model.Tune();
            Debug.WriteLine("Presolve called.");
            model.Presolve();
            Console.Write("\rRunning LP. Solving...                               \r");
            Debug.WriteLine("Optimize called.");
            model.Optimize();

            Graph solution = graph.Clone();
            HashSet<Edge> includedEdges = new HashSet<Edge>();
            for (int i = 0; i < solution.NumberOfEdges; i++)
            {
                var value = variables[i].Get(GRB.DoubleAttr.X);
                if (value == 1)
                    includedEdges.Add(solution.Edges[i]);
            }

            foreach (var edge in solution.Edges.ToList())
                if (!includedEdges.Contains(edge))
                    solution.RemoveEdge(edge);

            Console.Write("\r                                                  \r");

            return solution;
        }
Пример #10
0
        private void SetCurrentSolution(Graph solution, bool acceptWorseSolution = false)
        {
            if (CurrentSolution == null || acceptWorseSolution || solution.TotalCost < CurrentSolution.TotalCost)
            {
                CurrentSolution = solution.Clone();

                var removeVertices = CurrentSolution.Vertices.Where(x => CurrentSolution.GetDegree(x) == 0).ToList();
                foreach (var vertex in removeVertices)
                    CurrentSolution.RemoveVertex(vertex);

                CurrentSolutionCost = CurrentSolution.TotalCost;
                SolutionUpperBoundChanged?.Invoke(CurrentSolution.TotalCost);
            }
        }