Пример #1
0
        // 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);
        }
Пример #2
0
        // 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);
            }
        }