Пример #1
0
        public static Graph DFSInit(Graph G)
        {
            for (int width = Math.Min(G.vertices.Count, Math.Max(2, Program.BagsList.Count > 0 ? Program.BagsList.Max((b) => b.Count) : 0)); width <= G.vertices.Count; width++)
            {
                FastGraph  fastCopy         = new FastGraph(G);
                List <int> eliminationOrder = fastCopy.DFS(width, null);
                if (eliminationOrder != null) // We know that width is the minimum width possible
                {
                    return(G.TDFromEliminationOrder(eliminationOrder.Select((i) => fastCopy.baseVertices[i].OriginalVertex).ToList()));
                }
            }

            throw new Exception("DFS failed to find a solution");
        }
Пример #2
0
        // No more preprocessing rules apply, use branching or DP
        public Graph ComputeTD()
        {
            // Graph is too big and not dense enough. Try the separator technique
            if (vertices.Count >= 25 && edges.Count < 5 * vertices.Count)
            {
                Graph result = BranchOnSeparator();
                if (result != null)
                {
                    return(result);
                }
            }

#if USE_DFS
            return(FastGraph.DFSInit(this));
#else
            return(TreewidthDP());
#endif
        }
Пример #3
0
        // Computes a tree decomposition using the 2^n dynamic programming algorithm
        // Note: since this uses longs to represent partial results, only works for graphs up to 64 vertices
        public Graph TreewidthDP()
        {
            // Fall back on DFS
            if (vertices.Count > 64)
            {
                return(FastGraph.DFSInit(this));
            }

            List <Vertex> atTheEnd = new List <Vertex>();

            // Begin by finding a maximum clique, which should be the final bag.
            List <List <Vertex> > cliques = new List <List <Vertex> >();

            foreach (Vertex v in vertices.Keys) // Initialization: all vertices cliques of size 1
            {
                cliques.Add(new List <Vertex>(new Vertex[] { v }));
            }

            // Enumerate all cliques
            for (int i = 2; i <= vertices.Count; i++)
            {
                List <List <Vertex> > newCliques = new List <List <Vertex> >();
                foreach (List <Vertex> clique in cliques) // Enumerate over cliques of size i-1
                {
                    foreach (Vertex v in vertices.Keys)
                    {
                        if (v.Label <= clique[clique.Count - 1].Label)
                        {
                            continue;                                                       // Optimization: only consider cliques where the vertices are in increasing order
                        }
                        if (clique.All((u) => { return(edges.Contains(new Edge(u, v))); })) // Can we add the vertex (is it connected to everything else)?
                        {
                            // Found a new clique
                            List <Vertex> newClique = new List <Vertex>(clique);
                            newClique.Add(v);
                            newCliques.Add(newClique);
                            atTheEnd = newClique;
                        }
                    }
                }
                if (newCliques.Count == 0)
                {
                    break;
                }
                cliques = newCliques;

                // Limit the number of cases considered, as we want to limit the time and don't necessarily need to consider all of them
                cliques.Shuffle();
                cliques = cliques.Take(5000).ToList();
            }

            int width;

            // We use an iterative deepening approach: we start with the smallest possible width, and increase it by 1 until we find a width that fits
            // This simplifies the DP somewhat
            for (width = Math.Min(vertices.Count - 1, Math.Max(3, Program.BagsList.Count > 0 ? Program.BagsList.Max((b) => b.Count) - 1 : 0)); width < vertices.Count; width++)
            {
                atTheEnd = DPDecompose(width, cliques[0]);
                if (atTheEnd != null) // We know that width is the minimum width possible
                {
                    break;
                }
            }

            // Now compute the permutation that actually gives this width
            while (atTheEnd.Count < vertices.Count)
            {
                DPDecompose(width, atTheEnd);
            }

            return(TDFromEliminationOrder(atTheEnd));
        }