예제 #1
0
        // Removes a separator from the graph, and recursively computes a tree decomposition. The separator should be safe.
        // If check3isolated is true, then this also checks the property that given a separator of size 3, it should not split off any isolated vertices (or else it is not safe).
        // If any connected component has more than maximumSize vertices, do not proceed (balanced separator check)
        public Graph RemoveSeparator(List <Vertex> separator, bool check3isolated, int maximumSize)
        {
            // Compute the graph after removing separator
            List <Vertex> tempVertices = vertices.Keys.ToList();

            foreach (Vertex v in separator)
            {
                tempVertices.Remove(v);
            }

            // Get the connected components
            Graph componentsGraph            = new Graph(tempVertices);
            List <List <Vertex> > components = componentsGraph.getComponents();

            // If applicable, check that it is safe
            if (check3isolated && components.Any((c) => c.Count == 1))
            {
                return(null);
            }

            // Check balance
            if (components.Any((c) => c.Count > maximumSize))
            {
                return(null);
            }

            // Prepare the new tree decomposition: the root bag contains the separator
            Graph result = new Graph();

            Program.BagsList.Add(new List <Vertex>(separator));
            Vertex root = result.AddVertex(Program.BagsList.Count - 1);

            // Decompose each component
            foreach (List <Vertex> component in components)
            {
                // Create a new graph with the component in it
                Graph componentGraph = new Graph(component);

                // Add the separator
                foreach (Vertex v in separator)
                {
                    componentGraph.AddVertex(v);
                }

                foreach (Vertex u in separator)
                {
                    // Make the separator a clique
                    foreach (Vertex v in separator)
                    {
                        if (u.Label <= v.Label) // Not strictly necessary, but might save some time
                        {
                            continue;
                        }
                        componentGraph.AddEdge(u, v);
                    }
                    // And add edges from the separator to the rest
                    foreach (Vertex v in u.Adj)
                    {
                        componentGraph.AddEdge(u, v);
                    }
                }

                // Compute the TD of the component
                Graph TDComponent = componentGraph.Decompose();
                result.AddGraph(TDComponent);

                // Find an appropriate bag in the decomposition to connect our root bag to
                foreach (Vertex v in TDComponent.vertices.Keys)
                {
                    if (separator.All((u) => { return(Program.BagsList[v.Label].Contains(u)); }))
                    {
                        result.AddEdge(root, v);
                        break;
                    }
                }
            }

            return(result);
        }
예제 #2
0
        // Uses DP to find a decomposition with bag size at most upper
        public List <Vertex> DPDecompose(int upper, List <Vertex> atTheEnd)
        {
            // Make a list of the original labels
            List <int> vertexLabels = new List <int>();

            foreach (Vertex v in vertices.Keys)
            {
                vertexLabels.Add(v.Label);
            }

            // Replace the labels with 0...n-1
            Graph relabeledGraph = new Graph();

            foreach (Vertex v in vertices.Keys)
            {
                relabeledGraph.AddVertex(vertexLabels.IndexOf(v.Label));
            }

            // Copy the edges (using the relabeled vertices)
            foreach (Edge e in edges)
            {
                relabeledGraph.AddEdge(new Vertex(vertexLabels.IndexOf(e.a.Label)), new Vertex(vertexLabels.IndexOf(e.b.Label)));
            }

            // We know which vertices should go at the end
            List <Vertex> possibleVertices = new List <Vertex>(relabeledGraph.vertices.Keys.ToArray());

            foreach (Vertex v in atTheEnd)
            {
                possibleVertices.Remove(new Vertex(vertexLabels.IndexOf(v.Label)));
            }

            // Initialize the table: just the empty set
            HashSet <ulong> table = new HashSet <ulong>();

            table.Add(0);

            // Once we have processed n - upper - 1 vertices, in the next step there are only upper vertices not in S, and thus we always meet the restrictions
            for (int i = 0; i < Math.Min(vertices.Count - upper - 1, vertices.Count - atTheEnd.Count - 1); i++)
            {
                bool            islast   = i == Math.Min(vertices.Count - upper - 1, vertices.Count - atTheEnd.Count - 1) - 1;
                HashSet <ulong> newTable = new HashSet <ulong>();
#if SEQUENTIAL
                foreach (ulong S in table)
                {
                    if (islast && newTable.Count > 0)
                    {
                        break;
                    }

                    // Try to add each vertex
                    foreach (Vertex x in possibleVertices)
                    {
                        ulong newS = S | (1UL << x.Label);
                        if (newS == S || Q(newS, x) > upper)
                        {
                            continue;                                  // We either have already seen this vertex, or it would be too expensive
                        }
                        newTable.Add(newS);
                    }
                }
#else
                // Attempt to get parallelism working on the test system
                System.Threading.ThreadPool.SetMaxThreads(48 * 5, 48 * 5);
                System.Threading.ThreadPool.SetMinThreads(8, 8);
                Parallel.ForEach(table, () => new List <ulong>(), (S, loopState, partialResult) =>
                {
                    if (islast && (newTable.Count > 0 || partialResult.Count > 0))
                    {
                        return(partialResult);
                    }

                    // Try to add each vertex
                    foreach (Vertex x in possibleVertices)
                    {
                        ulong newS = S | (1UL << x.Label);
                        if (newS == S || Q(newS, x) > upper)
                        {
                            continue;                                  // We either have already seen this vertex, or it would be too expensive
                        }
                        partialResult.Add(newS);
                    }

                    return(partialResult);
                }, (localResult) => { lock (newTable) { foreach (ulong l in localResult)
                                                        {
                                                            newTable.Add(l);
                                                        }
                                      } });
#endif
                table = newTable;
                Program.TotalExpanded += table.Count;
            }

            // If there are any entries in the table, we know it's feasible
            if (table.Count > 0)
            {
                for (int i = 0; i < vertices.Count; i++)
                {
                    if ((table.First() & (1UL << i)) == 0 && !atTheEnd.Contains(vertices[new Vertex(vertexLabels[i])]))
                    {
                        atTheEnd.Add(vertices[new Vertex(vertexLabels[i])]);
                    }
                }
                return(atTheEnd);
            }
            else
            {
                return(null);
            }
        }
예제 #3
0
        static void HandleCase()
        {
            Stopwatch timer = new Stopwatch();

            timer.Start();

            // Parse the input graph
            Graph g = new Graph();

            for (string line = Console.ReadLine(); line != null; line = Console.ReadLine())
            {
                if (line.StartsWith("c") || line.StartsWith("n"))
                {
                    continue;             // Comment or dimacs node
                }
                if (line.StartsWith("p")) // Initialization
                {
                    string[] cf = line.Split(' ');

                    for (int i = 0; i < int.Parse(cf[2]); i++)
                    {
                        g.AddVertex(i);
                    }

                    continue;
                }

                // Dimacs-style edge
                if (line.StartsWith("e"))
                {
                    string[] vt = line.Split(' '); // Edge
                    g.AddVertex(int.Parse(vt[1]) - 1);
                    g.AddVertex(int.Parse(vt[2]) - 1);
                    g.AddEdge(g[int.Parse(vt[1]) - 1], g[int.Parse(vt[2]) - 1]);
                    continue;
                }

                // Something else, possibly an edge
                try
                {
                    string[] vt = line.Split(' '); // Edge
                    g.AddVertex(int.Parse(vt[0]) - 1);
                    g.AddVertex(int.Parse(vt[1]) - 1);
                    g.AddEdge(g[int.Parse(vt[0]) - 1], g[int.Parse(vt[1]) - 1]);
                }
                catch { }
            }

            if (g.vertices.Count == 0)
            {
                Console.WriteLine("s td 0 0 0");
                return;
            }

            // Run the algorithm
            BagsList       = new List <List <Vertex> >();
            TotalExpanded  = 0;
            SeparatorTried = 0;

            Graph TD        = g.Decompose();
            int   treewidth = BagsList.Max((b) => b.Count);

            // Write the output decomposition
            Console.Write("s td {0} {1} {2}", TD.vertices.Count, treewidth, g.vertices.Count); //s-line

            // Output bag contents
            int bc = 1;

            foreach (Vertex v in TD.vertices.Keys)
            {
                Console.WriteLine();
                Console.Write("b " + bc);
                foreach (Vertex v2 in BagsList[v.Label])
                {
                    Console.Write(" " + (v2.Label + 1));
                }
                v.Label = bc++;
            }

            // Output edges
            foreach (Edge e in TD.edges)
            {
                Console.WriteLine();
                Console.Write((e.a.Label) + " " + (e.b.Label));
            }

            timer.Stop();
            //Console.Write("tw\t" + treewidth + "\texp\t" + TotalExpanded + "\ttime\t" + Math.Round(timer.ElapsedMilliseconds / 1000d, 2));
        }