public static Dictionary <PartialSolution, int> Reduce_M4R(Dictionary <PartialSolution, int> table, double tr) { // No point further reducing something empty if (!table.Any() || table.First().Key.Subset == null) { return(table); } int nv = table.First().Key.Subset.LocalSubset.BitCount(); // Not worth reducing if (table.Count * tr <= (1 << (nv - 1))) { return(table); } Dictionary <PartialSolution, int> result; if (nv <= 1) { KeyValuePair <PartialSolution, int> minSol = table.Where((s) => s.Value == table.Values.Min()).First(); result = new Dictionary <PartialSolution, int>(); result.Add(minSol.Key, minSol.Value); return(result); } RankBased irb = new RankBased(table.First().Key.Subset); result = irb.M4RReduce(table); RankBased.ClearPool(); return(result); }
public Dictionary <PartialSolution, int> IntroduceEdgesIntoTable(Dictionary <PartialSolution, int> table, Edge[] edges) { if (table.Count == 0 || edges.Length == 0) { return(table); } Dictionary <PartialSolution, int> result = new Dictionary <PartialSolution, int>(); RankBased irb = new RankBased(table.First().Key.Subset); PriorityQueue <PartialSolution> pq = new PriorityQueue <PartialSolution>(table.Count * 2); foreach (KeyValuePair <PartialSolution, int> kvp in table) { pq.Enqueue(kvp.Key, kvp.Value); } HashSet <PartialSolution> seen = new HashSet <PartialSolution>(); while (!pq.IsEmpty()) { int weight = (int)pq.PeekDist(); PartialSolution ps = pq.Dequeue(); // HashSet is faster than RankBased if (!seen.Add(ps)) { continue; } // Solution is already represented by output if (!irb.AddSolution(ps)) { continue; } result.Add(ps, weight); Upsert(result, ps, weight); // Add edges to ps. Note that adding edges is not necessary if solution is already represented (since we could have added the same edges to the representatives instead) foreach (Edge e in edges) { if (ps.Find(e.To.Color) == ps.Find(e.From.Color)) { continue; } PartialSolution newSol = new PartialSolution(ps.Subset, ps); newSol.Union(e.To.Color, e.From.Color); pq.Enqueue(newSol, weight + e.Weight); } } RankBased.ClearPool(); 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); }