Пример #1
0
 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;
 }
Пример #2
0
 public PartialSolution(int width)
 {
     Subset    = null;
     UnionFind = new byte[width];
     for (byte i = 0; i < UnionFind.Length; i++)
     {
         UnionFind[i] = i;
     }
     hashCode = 0;
 }
Пример #3
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);
        }
Пример #4
0
        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));
        }
Пример #5
0
        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);
        }
Пример #6
0
        // 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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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));
        }
Пример #9
0
        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][];
        }
Пример #10
0
        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;
                }
            }
        }
Пример #11
0
        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();
            }
        }
Пример #12
0
        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);
        }
Пример #13
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);
        }