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; }
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 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; }
public Reducer(Graph instance) { _instance = instance.Clone(); _solutionUpperBound = Int32.MaxValue; _reductionUpperBound = 0; _running = false; Status = "Not running."; }
public Solver(Graph instance) { _instance = instance.Clone(); _running = false; _bls = new BLS(); _edgesToRemove = new ConcurrentQueue<Edge>(); _verticesToRemove = new ConcurrentQueue<Vertex>(); }
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; }
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; }
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; }
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; }
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); } }