public PartialSolution(VertexSubset subset) { Subset = subset; UnionFind = new byte[subset.ParentBag.ParentDecomposition.Width]; for (byte i = 0; i < UnionFind.Length; i++) { UnionFind[i] = i; } hashCode = 0; }
public PartialSolution(int width) { Subset = null; UnionFind = new byte[width]; for (byte i = 0; i < UnionFind.Length; i++) { UnionFind[i] = i; } hashCode = 0; }
public Dictionary <int, Dictionary <PartialSolution, int> > Forget(TDNode bag, Vertex[] vertices, Dictionary <int, Dictionary <PartialSolution, int> > table) { forgetSW.Start(); Dictionary <int, Dictionary <PartialSolution, int> > result = new Dictionary <int, Dictionary <PartialSolution, int> >(); int vertexMask = 0; foreach (Vertex v in vertices) { vertexMask |= (1 << v.Color); } byte[] tempUF = new byte[bag.ParentDecomposition.Width]; foreach (KeyValuePair <int, Dictionary <PartialSolution, int> > kvp in table) { int subset = kvp.Key; int newSubset = subset & ~vertexMask; Dictionary <PartialSolution, int> newDict = null; if (!result.TryGetValue(newSubset, out newDict)) { newDict = new Dictionary <PartialSolution, int>(); result.Add(newSubset, newDict); } foreach (KeyValuePair <PartialSolution, int> kvp2 in kvp.Value) { if (kvp2.Key.CountComponents() != kvp2.Key.CountComponents(newSubset)) { continue; // Check whether set remains connected } VertexSubset newVertexSubset = VertexSubset.Create(bag, newSubset, kvp2.Key.Subset, null); PartialSolution newPs = new PartialSolution(newVertexSubset, kvp2.Key); Upsert(newDict, newPs, kvp2.Value); } } foreach (KeyValuePair <int, Dictionary <PartialSolution, int> > kvp in table.ToList()) { table[kvp.Key] = RankBased.Reduce(kvp.Value, 0.125); } forgetSW.Stop(); Program.TableCount += result.Values.Sum((t) => t.Count); return(result); }
public override bool Equals(object obj) { if (obj == null) { return(false); } VertexSubset objSet = obj as VertexSubset; if (objSet == null) { return(false); } return(objSet.ParentBag == ParentBag && objSet.LocalSubset == LocalSubset && Object.ReferenceEquals(objSet.Left, Left) && Object.ReferenceEquals(objSet.Right, Right)); }
public static VertexSubset Create(TDNode ParentBag, int LocalSubset, VertexSubset Left, VertexSubset Right) { VertexSubset result = new VertexSubset() { ParentBag = ParentBag, LocalSubset = LocalSubset, Left = Left, Right = Right }; return(result); VertexSubset preExisting = null; if (Lookup.TryGetValue(result, out preExisting)) { return(preExisting); } Lookup[result] = result; return(result); }
// Joins two tables that have partial solutions with one type of vertex subset public Dictionary <PartialSolution, int> JoinTwo(TDNode bag, List <int> verticesInvolved, Dictionary <PartialSolution, int> leftTable, Dictionary <PartialSolution, int> rightTable) { Dictionary <PartialSolution, int> newTable = new Dictionary <PartialSolution, int>(); // Reducing before Join is almost certainly beneficial, use a low threshold leftTable = RankBased.Reduce(leftTable, 0.999); rightTable = RankBased.Reduce(rightTable, 0.999); KeyValuePair <PartialSolution, int>[] rightCopy = rightTable.ToArray(); foreach (KeyValuePair <PartialSolution, int> leftSol in leftTable) { foreach (KeyValuePair <PartialSolution, int> rightSol in rightCopy) { VertexSubset newSubset = VertexSubset.Create(bag, leftSol.Key.Subset.LocalSubset, leftSol.Key.Subset, rightSol.Key.Subset); PartialSolution newSol = new PartialSolution(newSubset, leftSol.Key); bool good = true; foreach (int i in verticesInvolved) { byte rep = rightSol.Key.Find(i); if (rep == i) { continue; } if (newSol.Find(i) == newSol.Find(rep)) { good = false; break; } newSol.Union(i, rep); } if (good) { Upsert(newTable, newSol, leftSol.Value + rightSol.Value); } } } // Do not call reduce here: the forget, introduce or join bag that comes next will take care of it //newTable = RankBased.Reduce(newTable, 0.5); return(newTable); }
public Dictionary <int, Dictionary <PartialSolution, int> > Join(TDNode bag, Dictionary <int, Dictionary <PartialSolution, int> > left, Dictionary <int, Dictionary <PartialSolution, int> > right) { joinSW.Start(); Dictionary <int, Dictionary <PartialSolution, int> > result = new Dictionary <int, Dictionary <PartialSolution, int> >(); foreach (KeyValuePair <int, Dictionary <PartialSolution, int> > kvp in left) { Dictionary <PartialSolution, int> leftTable = kvp.Value; Dictionary <PartialSolution, int> rightTable = null; if (!right.TryGetValue(kvp.Key, out rightTable) || !leftTable.Any() || !rightTable.Any()) { continue; } List <int> verticesInvolved = new List <int>(); foreach (Vertex v in bag.Bag) { if ((leftTable.First().Key.Subset.LocalSubset & (1 << v.Color)) != 0) { verticesInvolved.Add(v.Color); } } Dictionary <PartialSolution, int> newTable; newTable = JoinTwo(bag, verticesInvolved, leftTable, rightTable); //newTable = JoinTwoIncremental(bag, verticesInvolved, leftTable, rightTable); if (newTable.Count > 0) { result[kvp.Key] = newTable; } } VertexSubset.ClearLookup(); joinSW.Stop(); Program.TableCount += result.Values.Sum((t) => t.Count); return(result); }
public T Compute <T>(IDPAlgorithm <T> algorithm, TDNode parent) { VertexSubset.ClearLookup(); // Note: through preprocessing, certain subtrees might have become empty. Do not consider. IEnumerable <TDNode> children = Adj.Where((n) => n != parent && n.Subtree.Any()); if (children.Count() == 0) { return(algorithm.IntroduceEdges(algorithm.Introduce(this, Bag, algorithm.Leaf(ParentDecomposition.Width)), introduceEdges)); } if (children.Count() == 1) { TDNode child = children.First(); Vertex[] toForget = child.Bag.Where((v) => !this.BagContains(v)).OrderBy((v) => v.Adj.Where((w) => BagContains(w.To)).Count()).Reverse().ToArray(); Vertex[] toIntroduce = this.Bag.Where((v) => !child.BagContains(v)).ToArray(); if (toIntroduce.Length > 0) { return(algorithm.IntroduceEdges(algorithm.Introduce(this, toIntroduce, child.Compute(algorithm, this)), introduceEdges)); } if (toForget.Length > 0) { return(algorithm.IntroduceEdges(algorithm.Forget(this, toForget, child.Compute(algorithm, this)), introduceEdges)); } // No change? return(algorithm.IntroduceEdges(child.Compute(algorithm, this), introduceEdges)); } if (children.Count() > 2) { throw new Exception("TD not preprocessed!"); } TDNode left = children.ElementAt(0), right = children.ElementAt(1); return(algorithm.IntroduceEdges(algorithm.Join(this, IntroduceIfNecessary(algorithm, left, left.Compute(algorithm, this)), IntroduceIfNecessary(algorithm, right, right.Compute(algorithm, this))), introduceEdges)); }
uint[] tempArray; // Temporary array used to generate column public RankBased(VertexSubset subset) { vertices = new Vertex[subset.LocalSubset.BitCount()]; int pos = 0; foreach (Vertex v in subset.ParentBag.Bag) { if ((subset.LocalSubset & (1 << v.Color)) != 0) { vertices[pos++] = v; } } if (TW < vertices.Length - 1) { TW = vertices.Length - 1; arrayPool.Clear(); inUsePool.Clear(); } rowCount = 1 << (vertices.Length - 1); if (rowCount < 1) { rowCount = 1; } rowCountVector = (rowCount + VectorLength - 1) / VectorLength; elimOrder = new int[rowCount]; basisColumns = new Vector <uint> [rowCount][]; elimCount = 0; orderEpos = new int[rowCount]; orderErem = new int[rowCount]; orderEmask = new uint[rowCount]; tempArray = new uint[rowCountVector * Vector <uint> .Count]; inputColumns = new Vector <uint> [rowCount][]; }
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; } } }
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 Dictionary <int, Dictionary <PartialSolution, int> > Introduce(TDNode bag, Vertex[] vertices, Dictionary <int, Dictionary <PartialSolution, int> > table) { introSW.Start(); Vertex[] terminals = vertices.Where((v) => v.IsTerminal).ToArray(); Vertex[] nonterminals = vertices.Where((v) => !v.IsTerminal).ToArray(); Dictionary <int, Dictionary <PartialSolution, int> > result = new Dictionary <int, Dictionary <PartialSolution, int> >(); for (int i = 0; i < (1 << nonterminals.Length); i++) { List <Vertex> toAdd = new List <Vertex>(terminals.Length + i.BitCount()); foreach (Vertex v in terminals) { toAdd.Add(v); } for (int j = 0; j < nonterminals.Length; j++) { if ((i & (1 << j)) != 0) { toAdd.Add(nonterminals[j]); } } int addMask = 0; foreach (Vertex v in toAdd) { addMask |= (1 << v.Color); } List <Edge> introEdges = new List <Edge>(); foreach (Vertex v in toAdd) { foreach (Edge e in v.Adj) { if (bag.Bag.Contains(e.To) && !introEdges.Contains(e)) { introEdges.Add(e); } } } foreach (KeyValuePair <int, Dictionary <PartialSolution, int> > kvp in table) { int subset = kvp.Key; int newSubset = subset | addMask; Dictionary <PartialSolution, int> newDict = new Dictionary <PartialSolution, int>(); Dictionary <PartialSolution, int> localTable = RankBased.Reduce(kvp.Value, 0.999); foreach (KeyValuePair <PartialSolution, int> kvp2 in localTable) { VertexSubset newVertexSubset = VertexSubset.Create(bag, newSubset, kvp2.Key.Subset, null); newDict.Add(new PartialSolution(newVertexSubset, kvp2.Key), kvp2.Value); } if (introEdges.Where((e) => (newSubset & (1 << e.To.Color)) != 0).Count() > 2) { // Efficient method of introducing multiple edges at once and simultaneously running RankBased Reduce //newDict = IntroduceEdgesIntoTable(newDict, introEdges.Where((e) => (newSubset & (1 << e.To.Color)) != 0).ToArray()); newDict = IntroduceEdgesIntoTable(newDict, introEdges.Where((e) => (newSubset & (1 << e.To.Color)) != 0).ToArray()); } else { foreach (Edge e in introEdges) { if ((newSubset & (1 << e.To.Color)) != 0) { newDict = RankBased.Reduce(IntroduceEdge(newDict, e), 0.125); } } } if (newDict.Count > 0) { result.Add(newSubset, newDict); } } } introSW.Stop(); Program.TableCount += result.Values.Sum((t) => t.Count); return(result); }
// Different strategy for JoinTwo // The column obtained by joining two partial solutions is the bitwise AND of the columns corresponding to both solutions // Exploits this to attempt to speed up RBA public Dictionary <PartialSolution, int> JoinTwoIncremental(TDNode bag, List <int> verticesInvolved, Dictionary <PartialSolution, int> leftTable, Dictionary <PartialSolution, int> rightTable) { Dictionary <PartialSolution, int> newTable = new Dictionary <PartialSolution, int>(); RankBased irbL = new RankBased(leftTable.First().Key.Subset); RankBased irbR = new RankBased(rightTable.First().Key.Subset); Tuple <KeyValuePair <PartialSolution, int>, Vector <uint>[]>[] leftSolutions = leftTable.OrderBy((kvp2) => kvp2.Value).Select((s) => Tuple.Create(s, irbL.GetColumn(s.Key))).ToArray(); Tuple <KeyValuePair <PartialSolution, int>, Vector <uint>[]>[] rightSolutions = rightTable.OrderBy((kvp2) => kvp2.Value).Select((s) => Tuple.Create(s, irbR.GetColumn(s.Key))).ToArray(); if (leftSolutions.Length > (1 << (verticesInvolved.Count - 1))) { for (int i = 0; i < leftSolutions.Length; i++) { if (!irbL.AddSolution(leftSolutions[i].Item1.Key, leftSolutions[i].Item2)) { leftSolutions[i] = null; } } } if (rightSolutions.Length > (1 << (verticesInvolved.Count - 1))) { for (int i = 0; i < rightSolutions.Length; i++) { if (!irbR.AddSolution(rightSolutions[i].Item1.Key, rightSolutions[i].Item2)) { rightSolutions[i] = null; } } } leftSolutions = leftSolutions.Where((s) => s != null).ToArray(); rightSolutions = rightSolutions.Where((s) => s != null).ToArray(); Tuple <PartialSolution, PartialSolution, Vector <uint>[], Vector <uint>[], int>[] joinedSolutions = new Tuple <PartialSolution, PartialSolution, Vector <uint>[], Vector <uint>[], int> [leftSolutions.Length * rightSolutions.Length]; int pos = 0; foreach (Tuple <KeyValuePair <PartialSolution, int>, Vector <uint>[]> ls in leftSolutions) { foreach (Tuple <KeyValuePair <PartialSolution, int>, Vector <uint>[]> rs in rightSolutions) { joinedSolutions[pos++] = Tuple.Create(ls.Item1.Key, rs.Item1.Key, ls.Item2, rs.Item2, ls.Item1.Value + rs.Item1.Value); } } joinedSolutions = joinedSolutions.OrderBy((s) => s.Item5).ToArray(); //leftTable = RankBasedReduce(leftTable, 1); //rightTable = RankBasedReduce(rightTable, 1); RankBased irbJoined = new RankBased(leftTable.First().Key.Subset); HashSet <PartialSolution> psSeen = new HashSet <PartialSolution>(); foreach (Tuple <PartialSolution, PartialSolution, Vector <uint>[], Vector <uint>[], int> pair in joinedSolutions) { VertexSubset newSubset = VertexSubset.Create(bag, pair.Item1.Subset.LocalSubset, pair.Item1.Subset, pair.Item2.Subset); PartialSolution newSol = new PartialSolution(newSubset, pair.Item1); bool good = true; foreach (int i in verticesInvolved) { byte rep = pair.Item2.Find(i); if (rep == i) { continue; } if (newSol.Find(i) == newSol.Find(rep)) { good = false; break; } newSol.Union(i, rep); } if (!good || !psSeen.Add(newSol)) { continue; } Vector <uint>[] joinedColumn = RankBased.GetArray(); RankBased.AND(pair.Item3, pair.Item4, joinedColumn, irbJoined.rowCountVector); if (!irbJoined.AddSolution(newSol, joinedColumn)) { RankBased.ReleaseArray(joinedColumn); continue; } newTable.Add(newSol, pair.Item5); } RankBased.ClearPool(); return(newTable); }