public Vector <uint>[] GetColumn(PartialSolution s) { // Generate cuts for (int j = 0; j < tempArray.Length; j++) { tempArray[j] = 0; } if (vertices.Length <= 1) { tempArray[0] = 1; } else { GenerateCuts(0, 1, s, tempArray, vertices); } // Copy to SIMD vector Vector <uint>[] column = GetArray(); for (int j = 0; j < rowCountVector; j++) { column[j] = new Vector <uint>(tempArray, j * Vector <uint> .Count); } Program.GenerateCount++; return(column); }
public bool AddSolution(PartialSolution s, Vector <uint>[] currentColumn) { // Do elimination for (int j = 0; j < elimCount; j++) { //if (GetBit(currentColumn, elimOrder[j]) != 0) if ((currentColumn[orderEpos[j]][orderErem[j]] & orderEmask[j]) != 0) { XOR(currentColumn, basisColumns[elimOrder[j]], currentColumn, rowCountVector); } } int zeroPos = FirstNonZero(currentColumn, rowCountVector); // Column was redundant if (zeroPos == -1) { return(false); } // Do precomputation of (expensive) GetBit to speed things up *a lot* orderEpos[elimCount] = zeroPos / VectorLength; orderErem[elimCount] = (zeroPos % VectorLength) >> 5; orderEmask[elimCount] = 1u << ((zeroPos % VectorLength) & 31); // Add to basis elimOrder[elimCount++] = zeroPos; basisColumns[zeroPos] = currentColumn; return(true); }
// Old, slower, recursive method of generating a cut void GenerateCuts_old(int cutIndex, int pos, PartialSolution solution, uint[] column, Vertex[] vertices) { if (pos >= vertices.Length) { column[cutIndex >> 5] |= 1u << (cutIndex & 31); return; } bool canGoLeft = true, canGoRight = true; if (solution.Find(vertices[0].Color) == solution.Find(vertices[pos].Color)) { canGoRight = false; } for (int i = 1; i < pos; i++) { if (solution.Find(vertices[i].Color) == solution.Find(vertices[pos].Color)) { if ((cutIndex & (1 << (i - 1))) > 0) { canGoLeft = false; } else { canGoRight = false; } } } if (canGoLeft) { GenerateCuts_old(cutIndex, pos + 1, solution, column, vertices); } if (canGoRight) { GenerateCuts_old(cutIndex | (1 << (pos - 1)), pos + 1, solution, column, vertices); } }
static uint[] VerticesInPartition = new uint[33]; // One senitel element static void GenerateCuts(int cutIndex, int pos, PartialSolution solution, uint[] column, Vertex[] vertices) { int partitionChecker = 0; int partitionCount = 0; int zeroID = solution.Find(vertices[0].Color); for (int i = 1; i < vertices.Length; i++) { int id = solution.Find(vertices[i].Color); if (id == zeroID) { continue; // The connected component containing vertex 0 is fixed (representative is always lowest vertex) } int mask = 1 << id; if ((partitionChecker & mask) == 0) { partitionChecker |= mask; RootIndex[id] = partitionCount++; VerticesInPartition[RootIndex[id]] = 1u << (i - 1); } else { VerticesInPartition[RootIndex[id]] |= 1u << (i - 1); } } uint cut = 0; for (uint i = 0; i < (1 << partitionCount); i++) { uint delta = i ^ (i + 1); column[cut >> 5] |= 1u << (int)(cut & 31); int j = 0; while (delta != 0) { cut ^= VerticesInPartition[j]; j++; delta >>= 1; } } }
public PartialSolution(VertexSubset subset, PartialSolution parent) { Subset = subset; UnionFind = new byte[subset == null ? 0 : subset.ParentBag.ParentDecomposition.Width]; for (byte i = 0; i < UnionFind.Length; i++) { UnionFind[i] = parent.UnionFind == null ? i : parent.UnionFind[i]; } hashCode = 0; // Check if any vertices have been forgotten if (parent.Subset == null || ((subset.LocalSubset ^ parent.Subset.LocalSubset) & parent.Subset.LocalSubset) == 0) { return; } // Rework union-find to fix forgotten vertices for (byte i = 0; i < UnionFind.Length; i++) { if ((Subset.LocalSubset & (1 << i)) != 0 && (parent.Subset.LocalSubset & (1 << i)) != 0) { byte rep = Find(i); if ((Subset.LocalSubset & (1 << rep)) == 0) { UnionFind[rep] = i; UnionFind[i] = i; } } } for (byte i = 0; i < UnionFind.Length; i++) { if ((Subset.LocalSubset & (1 << i)) == 0) { UnionFind[i] = i; } } }
public override bool Equals(object obj) { if (obj == null) { return(false); } PartialSolution objSol = (PartialSolution)obj; if (Subset.LocalSubset != objSol.Subset.LocalSubset) { return(false); } for (int i = 0; i < UnionFind.Length; i++) { if (Find(i) != objSol.Find(i)) { return(false); } } return(true); }
static void Main(string[] args) { int seed = 4321; // Prescribed method of initializing randomness if (Array.IndexOf(args, "-s") < args.Length - 1) { try { seed = int.Parse(args[Array.IndexOf(args, "-s") + 1]); } catch { } } Stopwatch sw = new Stopwatch(); //StreamWriter outSW = new StreamWriter("output.txt"); //Console.SetOut(outSW); //for (int i = 79; i < 200; i += 2) { r = new Random(seed); //outSW.Flush(); //if (i == 79) continue; // This testcase is very large and slow sw.Restart(); //if (Debug) Console.Write(i.ToString().PadLeft(3, '0') + " "); StreamReader sr = null; //sr = new StreamReader(String.Format("../../../../../instances/instance{0}.gr", i.ToString().PadLeft(3, '0'))); g = Graph.Parse(sr ?? Console.In); decomposition = TreeDecomposition.Parse(sr ?? Console.In, g); InitUF(g); List <Edge> forcedEdges = new List <Edge>(); // Find edges that are forced because they are between two terminals and there is no path with lighter bottleneck foreach (Edge e in g.Edges.OrderBy((e) => e.Weight).ThenBy((e) => e.To.IsTerminal && e.From.IsTerminal ? 0 : 1)) { if (Find(e.From.Id) == Find(e.To.Id)) { continue; } if (e.To.IsTerminal && e.From.IsTerminal) { forcedEdges.Add(e); } Union(e.From.Id, e.To.Id); } if (Debug) { Console.WriteLine("Forced: " + forcedEdges.Count); } // Use Dreyfus-Wagner or Erickson-Monma-Veinott if FPT (in nubmer of terminals) is faster than treewidth DP if (Math.Pow(5.0, decomposition.Width - Math.Log(1000000, 5.0)) > Math.Pow(3.0, g.Vertices.Where((v) => v.IsTerminal).Count() - forcedEdges.Count - Math.Log(1000000, 3.0))) { foreach (Edge e in forcedEdges) { if (e.From.IsTerminal) { e.From.IsTerminal = false; } else { e.To.IsTerminal = false; } e.From.Adj.Add(new Edge(e.From, e.To, 0)); e.To.Adj.Add(new Edge(e.To, e.From, 0)); } //new DreyfusWagner(g, forcedEdges).Solve(); new EricksonMonmaVeinott(g, forcedEdges).Solve(); if (Debug) { Console.WriteLine(sw.ElapsedMilliseconds); //continue; // Should be commented out when Debug is false } return; } XORCount = 0; TableCount = 0; GenerateCount = 0; // Actually run the DP algorithm decomposition.FindOptimalRoot(); SteinerAlgorithm algo = new SteinerAlgorithm(); Dictionary <int, Dictionary <PartialSolution, int> > result = decomposition.Compute(algo); if (Debug) { algo.Diagnostics(); } // Find best solution int bestVal = int.MaxValue; PartialSolution bestSol = new PartialSolution(); foreach (Dictionary <PartialSolution, int> table in result.Values) { foreach (KeyValuePair <PartialSolution, int> kvp in table) { if (kvp.Value >= bestVal || kvp.Key.CountComponents() > 1) { continue; } bestVal = kvp.Value; bestSol = kvp.Key; } } if (bestVal == int.MaxValue) { Console.WriteLine("Impossible"); } else { if (Debug) { Console.Write(Math.Round(sw.ElapsedMilliseconds / 1000.0, 1) + "s\tSolutions: {0}\tRows Generated: {1}\tXORCount: {2}\t", TableCount, GenerateCount, XORCount); } Console.WriteLine("VALUE " + bestVal); if (Debug) { Console.WriteLine(); } // Reconstruct subset of vertices HashSet <int> solution = new HashSet <int>(); Stack <VertexSubset> subsets = new Stack <VertexSubset>(); subsets.Push(bestSol.Subset); while (subsets.Count > 0) { VertexSubset subset = subsets.Pop(); if (subset == null || subset.ParentBag == null) { continue; } subsets.Push(subset.Left); subsets.Push(subset.Right); foreach (Vertex v in subset.ParentBag.Bag) { if ((subset.LocalSubset & (1 << v.Color)) != 0) { solution.Add(v.Id); } } } InitUF(g); // Compute MST on vertex set int total = 0; int count = 0; foreach (Edge e in g.Edges.OrderBy((e) => e.Weight).ThenBy((e) => Math.Min(e.To.Id, e.From.Id)).ThenBy((e) => Math.Max(e.To.Id, e.From.Id))) { if (!solution.Contains(e.To.Id) || !solution.Contains(e.From.Id)) { continue; } if (Find(e.To.Id) == Find(e.From.Id)) { continue; } Union(e.To.Id, e.From.Id); if (!Debug) { Console.WriteLine(Math.Min((e.From.Id + 1), (e.To.Id + 1)) + " " + Math.Max((e.From.Id + 1), (e.To.Id + 1))); } total += e.Weight; count++; } } } if (Debug) { Console.ReadLine(); } }
public bool AddSolution(PartialSolution s) { return(AddSolution(s, GetColumn(s))); }