public override DecompositionTree Construct(Graph graph, WidthParameter widthparameter)
        {
            DecompositionTree tree = new DecompositionTree(graph, widthparameter);

            // Create the leaves.
            DecompositionNode[] nodes = new DecompositionNode[graph.Vertices.Count];
            for (int i = 0; i < nodes.Length; i++)
            {
                tree.Nodes[i] = nodes[i] = new DecompositionNode(new BitSet(nodes.Length, graph.Vertices[i].Index), i, tree);
            }

            int size = nodes.Length;

            while (size > 1)
            {
                // Find the pair of nodes whose combination is of minimal width.
                double min = double.PositiveInfinity;
                int    first = -1, second = -1;
                for (int i = 0; i < size; i++)
                {
                    for (int j = i + 1; j < size; j++)
                    {
                        double width = widthparameter.GetWidth(graph, nodes[i].Set | nodes[j].Set);
                        if (width < min)
                        {
                            min    = width;
                            first  = i;
                            second = j;
                        }
                    }
                }
                // Create the parent and connect it to its children.
                DecompositionNode node = new DecompositionNode(nodes[first].Set | nodes[second].Set, nodes.Length * 2 - size, tree);
                tree.Attach(node, nodes[first], Branch.Left);
                tree.Attach(node, nodes[second], Branch.Right);
                tree.Nodes[node.Index] = node;

                // Update the active set of nodes.
                nodes[first]  = node;
                nodes[second] = nodes[size - 1];

                size--;
            }

            tree.Attach(null, nodes[0], Branch.Left);
            tree.ComputeWidth();
            return(tree);
        }
        /// <summary>
        /// Construct a linear decomposition tree from the given starting vertex.
        /// </summary>
        protected DecompositionTree construct(Graph graph, WidthParameter widthparameter, Vertex start)
        {
            DecompositionTree result = new DecompositionTree(graph, widthparameter);

            int    index     = 0;
            BitSet leftbits  = new BitSet(graph.Vertices.Count, start.Index);
            BitSet rightbits = ~leftbits;

            BitSet neighborhood = new BitSet(start.Neighborhood);

            this.add(result, start, index++);

            while (!rightbits.IsEmpty)
            {
                Vertex selected = null;
                double best     = double.PositiveInfinity;

                var candidates = this.candidates(graph, rightbits, leftbits, neighborhood);
                foreach (var candidate in candidates)
                {
                    BitSet left = new BitSet(leftbits);
                    left[candidate.Index] = true;
                    BitSet right = new BitSet(rightbits);
                    right[candidate.Index] = false;
                    double width = widthparameter.GetWidth(graph, left, right);
                    if (width < best)
                    {
                        best     = width;
                        selected = candidate;
                    }
                }

                leftbits[selected.Index]  = true;
                rightbits[selected.Index] = false;
                neighborhood.Or(selected.Neighborhood);
                neighborhood[selected.Index] = false;

                this.add(result, selected, index);
                index += 2;
            }

            return(result);
        }
예제 #3
0
        public override DecompositionTree Construct(Graph graph, WidthParameter widthparameter)
        {
            DecompositionTree tree = new DecompositionTree(graph, widthparameter);

            // Create the leaves.
            DecompositionNode[] nodes = new DecompositionNode[graph.Vertices.Count];
            for (int i = 0; i < nodes.Length; i++)
            {
                tree.Nodes[i] = nodes[i] = new DecompositionNode(new BitSet(nodes.Length, graph.Vertices[i].Index), i, tree);
            }

            int size = nodes.Length;

            while (size > 1)
            {
                int first  = this.rng.Next(size);
                int second = this.rng.Next(size - 1);
                if (second <= first)
                {
                    second++;
                }

                // Create the parent and connect it to its children.
                DecompositionNode node = new DecompositionNode(nodes[first].Set | nodes[second].Set, nodes.Length * 2 - size, tree);
                tree.Attach(node, nodes[first], Branch.Left);
                tree.Attach(node, nodes[second], Branch.Right);
                tree.Nodes[node.Index] = node;

                // Update the active set of nodes.
                nodes[first]  = node;
                nodes[second] = nodes[size - 1];

                size--;
            }

            tree.Attach(null, nodes[0], Branch.Left);
            tree.ComputeWidth();
            return(tree);
        }
 /// <summary>
 /// Construct a decomposition tree from the graph.
 /// </summary>
 /// <param name="graph">The graph that will be decomposed.</param>
 /// <param name="widthparameter">The width-parameter used to create the decomposition.</param>
 /// <returns>A binary decomposition tree of the graph.</returns>
 public abstract DecompositionTree Construct(Graph graph, WidthParameter widthparameter);
예제 #5
0
        public static void RunUserTest()
        {
            Console.WriteLine("Path to graph file? Defaults to the anna graph from the TreewidthLIB set.");
            string pathToGraph = Console.ReadLine();

            if (pathToGraph.Length == 0)
            {
                pathToGraph = @"..\..\ExampleGraphs\anna.dgf";
            }
            Graph graph = Parser.ParseGraphFromDGF(pathToGraph);

            Console.WriteLine("Width Parameter is (M)aximum-matching, (R)ank or (B)oolean? Defaults to rank-width.");
            WidthParameter width = null;
            string         widthParameterString = Console.ReadLine().ToLower();

            if (widthParameterString.Length == 0)
            {
                width = new RankWidth();
            }
            else
            {
                switch (widthParameterString.ToLower()[0])
                {
                case 'm':
                    width = new MaximumMatchingWidth();
                    break;

                case 'b':
                    width = new BooleanWidth();
                    break;

                default:
                    width = new RankWidth();
                    break;
                }
            }

            Console.WriteLine("Local search duration in seconds? Defaults to 60 seconds.");
            int localSearchDuration = 0;

            if (!int.TryParse(Console.ReadLine(), out localSearchDuration))
            {
                localSearchDuration = 60;
            }

            Console.WriteLine("Seed for the random number generator? Defaults to a random seed.");
            int seed = -1;

            if (!int.TryParse(Console.ReadLine(), out seed))
            {
                Random r = new Random();
                seed = r.Next();
                Console.WriteLine("Seed is " + seed);
            }
            Random rng = new Random(seed);

            Console.WriteLine("Should reduction rules be applied, (Y)es or (N)o? Defaults to yes.");
            string reductionString   = Console.ReadLine().ToLower();
            bool   useReductionRules = reductionString.Length == 0 || reductionString[0] != 'n';


            double totalseconds = 0;

            Console.WriteLine();
            Console.WriteLine("---------------------- Starting -----------------------");
            Console.WriteLine();

            Graph[] graphs = null;
            if (useReductionRules)
            {
                int originalvertexcount = graph.Vertices.Count;
                Console.WriteLine($"Graph {Path.GetFileNameWithoutExtension(pathToGraph)} consists of {originalvertexcount} vertices.");
                Console.WriteLine($"Applying the reduction rules...");
                graphs = width.ApplyReductionRules(graph);
                Console.WriteLine($"Number of vertices removed by the reduction rules = {originalvertexcount - graphs.Sum(g => g.Vertices.Count)}");
                Console.WriteLine($"The reduction rules splitted the graph in {graphs.Length} subgraphs of sizes {string.Join(", ", graphs.Select(g => g.Vertices.Count))}.");
            }
            else
            {
                graphs = new Graph[] { graph }
            };

            Console.WriteLine();

            Console.WriteLine("Constructing initial solution...");
            Stopwatch             sw          = Stopwatch.StartNew();
            ConstructionHeuristic constructor = new GreedyLinearConstructor(rng);

            DecompositionTree[] trees = graphs.Select(g => constructor.Construct(g, width)).ToArray();

            sw.Stop();
            totalseconds += sw.ElapsedMilliseconds / 1000.0;
            Console.WriteLine($"Finished construction of initial solution in {(sw.ElapsedMilliseconds / 1000).ToString("F2")} seconds.");
            Console.WriteLine($"Initial {width.Name} = {string.Join(", ", trees.Select(tree => tree.Width.ToString("F2")))}");
            Console.WriteLine($"Initial cost = {string.Join(", ", trees.Select(tree => tree.Cost.ToString("F2")))}");

            Console.WriteLine();

            Console.WriteLine("Improving solution with DP...");
            sw.Restart();
            OptimalOrderedTree oot = new OptimalOrderedTree();

            trees = trees.Select(tree => oot.Construct(tree)).ToArray();
            sw.Stop();
            totalseconds += sw.ElapsedMilliseconds / 1000.0;
            Console.WriteLine($"Finished DP in {(sw.ElapsedMilliseconds / 1000.0).ToString("F2")} seconds.");
            Console.WriteLine($"Resulting {width.Name} = {string.Join(", ", trees.Select(tree => tree.Width.ToString("F2")))}");
            Console.WriteLine($"Resulting cost = {string.Join(", ", trees.Select(tree => tree.Cost.ToString("F2")))}");

            Console.WriteLine();

            Console.WriteLine("Improving solution with local search...");
            LocalSearchAlgorithm localsearch = new VariableNeighborhoodSearch(trees, new LocalSearchOperator[] { new MoveOperator(), new SwapOperator() }, rng);

            localsearch.Run(localSearchDuration);
            totalseconds += localsearch.CurrentComputationTime;
            Console.WriteLine($"Finished local search in {localsearch.CurrentComputationTime.ToString("F2")} seconds.");
            Console.WriteLine($"Total iterations = {localsearch.Iterations}");
            Console.WriteLine($"Explored solutions = {localsearch.ExploredSolutions}");
            Console.WriteLine($"Best {width.Name} = {string.Join(", ", trees.Select(tree => tree.Width.ToString("F2")))}");
            Console.WriteLine($"Best cost = {string.Join(", ", trees.Select(tree => tree.Cost.ToString("F2")))}");
            Console.WriteLine("Best decomposition trees:");
            for (int i = 0; i < trees.Length; i++)
            {
                Console.WriteLine($"{i}: {trees[i].Root}");
            }

            Console.WriteLine();

            Console.WriteLine("Cache statistics:");
            Console.WriteLine($"    request count = {width.CacheRequests}");
            Console.WriteLine($"    hit ratio = {width.CacheHitRatio.ToString("F3")}");

            Console.WriteLine();

            Console.WriteLine("Write result to disk? (Y)es / (N)o, defaults to Yes.");
            string outputResponseString = Console.ReadLine().ToLower();

            if (outputResponseString.Length == 0 || outputResponseString[0] == 'y')
            {
                Console.WriteLine("Output directory? Defaults to \\output.");
                string outputDirectory = Console.ReadLine();
                if (outputDirectory.Length == 0)
                {
                    outputDirectory = "output";
                }
                Console.WriteLine($"Stored the result as {WriteResult(pathToGraph, outputDirectory, trees, seed, totalseconds)}");
            }
            else
            {
                Console.ReadLine();
            }
        }
        public override DecompositionTree Construct(Graph graph, WidthParameter widthparameter)
        {
            int index = 0;
            DecompositionTree tree = new DecompositionTree(graph, widthparameter);
            DecompositionNode root = new DecompositionNode(~(new BitSet(tree.VertexCount)), index, tree);

            tree.Nodes[index++] = root;
            tree.Attach(null, root, Branch.Left);

            List <DecompositionNode> candidates = new List <DecompositionNode>();

            candidates.Add(root);

            while (candidates.Count > 0)
            {
                // Select a random childless internal node.
                DecompositionNode parent = candidates[this.rng.Next(candidates.Count)];
                candidates.Remove(parent);

                // Shuffle its set of vertices.
                int[] indices = parent.Set.ToArray();
                indices.Shuffle(this.rng);

                // Split the set randomly into two non-empty sets.
                int split = 1 + this.rng.Next(indices.Length - 2);

                // Create its children.
                DecompositionNode left = null;
                if (split == 1)
                {
                    left = new DecompositionNode(graph.Vertices[indices[0]], index, tree);
                }
                else
                {
                    BitSet leftset = new BitSet(tree.VertexCount);
                    for (int i = 0; i < split; i++)
                    {
                        leftset[indices[i]] = true;
                    }
                    left = new DecompositionNode(leftset, index, tree);
                    candidates.Add(left);
                }
                tree.Nodes[index++] = left;
                tree.Attach(parent, left, Branch.Left);

                DecompositionNode right = null;
                if (split == indices.Length - 1)
                {
                    right = new DecompositionNode(graph.Vertices[indices[indices.Length - 1]], index, tree);
                }
                else
                {
                    BitSet rightset = new BitSet(tree.VertexCount);
                    for (int i = split; i < indices.Length; i++)
                    {
                        rightset[indices[i]] = true;
                    }
                    right = new DecompositionNode(rightset, index, tree);
                    candidates.Add(right);
                }
                tree.Nodes[index++] = right;
                tree.Attach(parent, right, Branch.Right);
            }

            tree.ComputeWidth();
            return(tree);
        }
 public override DecompositionTree Construct(Graph graph, WidthParameter widthparameter)
 {
     return(this.construct(graph, widthparameter, graph.Vertices[this.random.Next(graph.Vertices.Count)]));
 }
 public DecompositionTree(DecompositionTree tree, WidthParameter width = null) : this(tree.Graph, width != null ? width : tree.WidthParameter)
 {
     this.Root = tree.Root.CopyTree(this, null);
 }
 public DecompositionTree(Graph graph, WidthParameter parameter)
 {
     this.Graph          = graph;
     this.WidthParameter = parameter;
     this.Nodes          = new DecompositionNode[graph.Vertices.Count * 2 - 1];
 }