// 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); }
// Splits up joins into binary joins in a heuristically efficient way public void DeconstructJoins(TDNode parent) { IEnumerable <TDNode> children = Adj.Where((n) => n != parent); foreach (TDNode child in children) { child.DeconstructJoins(this); } if (children.Count() <= 2) { return; } List <Tuple <int, TDNode> > toJoin = new List <Tuple <int, TDNode> >(); foreach (TDNode child in children) { int code = 0; foreach (Vertex v in child.Bag) { code |= 1 << v.Color; } toJoin.Add(Tuple.Create(code, child)); child.Adj.Remove(this); } this.Adj.Clear(); Adj.Add(parent); while (toJoin.Count > 2 || (toJoin.Count == 2 && (toJoin[0].Item1 | toJoin[1].Item1).BitCount() < Bag.Length)) { int min = int.MaxValue; Tuple <int, TDNode> left = null, right = null; for (int i = 0; i < toJoin.Count; i++) { for (int j = i + 1; j < toJoin.Count; j++) { if ((toJoin[i].Item1 | toJoin[j].Item1).BitCount() < min) { min = (toJoin[i].Item1 | toJoin[j].Item1).BitCount(); left = toJoin[i]; right = toJoin[j]; } } } toJoin.Remove(left); toJoin.Remove(right); TDNode newNode = new TDNode((left.Item1 | right.Item1).BitCount(), ParentDecomposition, VertexByColor.Length); toJoin.Add(Tuple.Create(left.Item1 | right.Item1, newNode)); newNode.Adj.Add(left.Item2); newNode.Adj.Add(right.Item2); left.Item2.Adj.Add(newNode); right.Item2.Adj.Add(newNode); ParentDecomposition.Nodes.Add(newNode); int c = 0; for (int i = 0; i < VertexByColor.Length; i++) { if (left.Item2.VertexByColor[i] != null) { newNode.Bag[c++] = left.Item2.VertexByColor[i]; newNode.VertexByColor[i] = left.Item2.VertexByColor[i]; } else if (right.Item2.VertexByColor[i] != null) { newNode.Bag[c++] = right.Item2.VertexByColor[i]; newNode.VertexByColor[i] = right.Item2.VertexByColor[i]; } } } this.Adj.Add(toJoin[0].Item2); toJoin[0].Item2.Adj.Add(this); if (toJoin.Count > 1) { this.Adj.Add(toJoin[1].Item2); toJoin[1].Item2.Adj.Add(this); } }