IEnumerable <BitVector> enumerateCsgRecursive(JoinGraph graph, BitVector S, BitVector X) { // N = neighbour(S) \ X BitVector N = SetOp.Substract(graph.NeighboursExcluding(S), X); // Console.WriteLine("N: " + BitHelper.ToString(N)); // for all non-empty S' subsetof(N), emit (S union S') if (N != SetOp.EmptySet) { VancePartition partitioner = new VancePartition(N); foreach (var S_prime in partitioner.Next(true)) { yield return(SetOp.Union(S, S_prime)); } // for all non-empty S' subsetof(N), recursively invoke (graph, (S union S'), (X union N)) partitioner = new VancePartition(N); foreach (var S_prime in partitioner.Next(true)) { foreach (var v in enumerateCsgRecursive(graph, SetOp.Union(S, S_prime), SetOp.Union(X, N))) { yield return(v); } } } }
// Naive partitioning // Similar to DPBushy algorithm IEnumerable <CsgCmpPair> NaiveNext(JoinGraph graph, BitVector S) { // it is connected because the 1st iteration is connected and when // we generate for next iteration, we checked S1,S2. // Debug.Assert(graph.IsConnected(S)); VancePartition partitioner = new VancePartition(S); foreach (var S1 in partitioner.Next()) { c1_++; BitVector S2 = SetOp.Substract(S, S1); if (S1 < S2) { if (!graph.IsConnected(S1) || !graph.IsConnected(S2)) { continue; } yield return(new CsgCmpPair(graph, S1, S2)); } } }
override internal PhysicNode Run(JoinGraph graph, BigInteger expectC1) { int ntables = graph.vertices_.Count; Console.WriteLine("DP_Bushy #tables: " + ntables); // initialization: enqueue all single tables InitByInsertBasicTables(graph); // loop through all candidates trees, CP included ulong c1 = 0, c2 = 0; for (BitVector S = 1; S < (1 << ntables); S++) { if (bestTree_[S] != null) { continue; } // need connected subgraphs if not consider CP if (!graph.IsConnected(S)) { // this partition enumeration is only to record #c2 c2 += (ulong)(new VancePartition(S)).Next().ToArray().Length; continue; } // for all S_1 subset of S do VancePartition partitioner = new VancePartition(S); foreach (var S1 in partitioner.Next()) { c2++; BitVector S2 = SetOp.Substract(S, S1); // requires S1 < S2 to avoid commutative duplication Debug.Assert(S1 != S2); if (S1 < S2) { // need connected subgraphs if not consider CP if (!graph.IsConnected(S1) || !graph.IsConnected(S2)) { continue; } // find a connected pair, get the best join tree between them c1++; var currTree = CreateMinimalJoinTree(bestTree_[S1], bestTree_[S2]); Debug.Assert(bestTree_[S].Cost() == currTree.Cost()); } } } // verify # loops for enumeration completeness: // 1. mumber of bushy trees // 2. expectC2/c2: number of trees DP considered (P68) and number of trees generated // 3. expectC1/c1: number of trees considered // var nbushy = Space.Count_General_Bushy_CP(ntables); var expectC2 = BigInteger.Pow(3, ntables) - BigInteger.Pow(2, ntables + 1) + 1; Console.WriteLine("bushy: {0}, dp: {1} == c2: {2}; expected c1: {3} == c1: {4}", nbushy, expectC2, c2, expectC1, c1); Debug.Assert(expectC2 == c2); if (!expectC1.IsZero) { Debug.Assert(c1 == expectC1); } var result = bestTree_[(1 << ntables) - 1]; Console.WriteLine(result.Explain()); return(result); }