/// <summary> /// Updates the vertex-set and the width properties of all ancestors of a node in a bottom-up fashion, until the given ancestor is reached. /// </summary> /// <param name="child">A descendant of all nodes that will be updated.</param> /// <param name="end">The updating of the ancestor will stop once this node is reach. The end-node itself will not be updated.</param> /// <param name="add">The vertices that will be added to the vertex-set of the ancestors. NULL can be passed if no vertices should be added.</param> /// <param name="remove">The vertices that will be removed from the vertex-set of the ancestors. NULL can be passed if no vertices should be removed.</param> protected void updateAncestors(DecompositionNode child, DecompositionNode end, BitSet add, BitSet remove) { bool addToVertexSet = add != null && !add.IsEmpty; bool removeFromVertexSet = remove != null && !remove.IsEmpty; for (DecompositionNode ancestor = child?.Parent; ancestor != end && ancestor != null; child = ancestor, ancestor = ancestor.Parent) { if (addToVertexSet || removeFromVertexSet) { if (addToVertexSet) { ancestor.Set.Or(add); } if (removeFromVertexSet) { ancestor.Set.Exclude(remove); } ancestor.UpdateWidthProperties(); } else { ancestor.UpdateWidthProperties(false); } } }
/// <summary> /// Computes the maximum width and the sum of widths of the nodes of the subtree ... /// </summary> /// <param name="child">The node whose subtree has already been computed.</param> /// <param name="end">The parent of the root of the subtree that we want to compute.</param> /// <param name="add">he vertices that will be added to the vertex-set of the ancestors. NULL can be passed if no vertices should be added.</param> /// <param name="remove">The vertices that will be removed from the vertex-set of the ancestors. NULL can be passed if no vertices should be removed.</param> /// <param name="maximum">The maximum width of the subtree, excluding the width of the subtree rooted at the child.</param> /// <param name="sum">The sum of the width of the nodes of the subtree, excluding the sum of the subtree rooted at the child.</param> protected void computeWidthAncestors(DecompositionNode child, DecompositionNode end, BitSet add, BitSet remove, ref double maximum, ref double sum) { bool addToVertexSet = add != null && !add.IsEmpty; bool removeFromVertexSet = remove != null && !remove.IsEmpty; for (DecompositionNode ancestor = child?.Parent; ancestor != end && ancestor != null; child = ancestor, ancestor = ancestor.Parent) { double width = ancestor.Width; if (addToVertexSet || removeFromVertexSet) { BitSet set = new BitSet(ancestor.Set); if (addToVertexSet) { set.Or(add); } if (removeFromVertexSet) { set.Exclude(remove); } width = this.Tree.WidthParameter.GetWidth(this.Tree.Graph, set); } maximum = Math.Max(maximum, Math.Max(width, child.Sibling.SubTreeWidth)); sum += width + child.Sibling.SubTreeSum; } }
protected override double computeCost() { double maximum = Math.Max(this.SelectedNodeLeft.SubTreeWidth, this.SelectedNodeRight.SubTreeWidth), sum = this.SelectedNodeLeft.SubTreeSum + this.SelectedNodeRight.SubTreeSum; // Find the first common ancestor of a and b. DecompositionNode common = this.findCommonAncestor(this.SelectedNodeLeft, this.SelectedNodeRight); // Compute the width of the ancestors of a up to the common ancestor. this.computeWidthAncestors(this.SelectedNodeLeft, common, this.SelectedNodeRight.Set, this.SelectedNodeLeft.Set, ref maximum, ref sum); // Compute the width of the ancestors of b up to the common ancestor. this.computeWidthAncestors(this.SelectedNodeRight, common, this.SelectedNodeLeft.Set, this.SelectedNodeRight.Set, ref maximum, ref sum); // Compute the width of the first common ancestor. if (maximum < common.Width) { maximum = common.Width; } sum += common.Width; // Compute the width of the remaining common ancestors. this.computeWidthAncestors(common, null, null, null, ref maximum, ref sum); double topwidth = this.Tree.Root.Right.Width; if (common.IsRoot) { BitSet set = this.Tree.Root.Right.Set - this.SelectedNodeRight.Set | this.SelectedNodeLeft.Set; topwidth = this.Tree.WidthParameter.GetWidth(this.Tree.Graph, set); } return(DecompositionTree.ComputeCost(maximum, this.Tree.VertexCount, sum, topwidth)); }
/// <summary> /// Searches for the first common ancestor of two nodes. /// </summary> /// <param name="n1">One of the nodes.</param> /// <param name="n2">The other node.</param> /// <returns>The common ancestor.</returns> protected DecompositionNode findCommonAncestor(DecompositionNode n1, DecompositionNode n2) { for (DecompositionNode ancestor = n1; ancestor != null; ancestor = ancestor.Parent) { if (ancestor.Set.IsSupersetOf(n2.Set)) { return(ancestor); } } throw new KeyNotFoundException(); }
public override LocalSearchOperation GetRandomOperation(DecompositionTree tree, Random rng) { // No operations available. if (tree.Nodes.Length <= 3) { return(null); } // Select a random node that will be moved to a different position in the tree. int index = this.getRandomNonRootIndex(tree, rng); DecompositionNode selected = tree.Find(index); // Select a random node that will become the new sibling of the selected node. int candidateCount = tree.Nodes.Length - selected.SubTreeSize - 2, positionIndex = 1 + rng.Next(candidateCount); // We need to ensure that we do not select a node in the subtree of the selected node, nor its current parent and sibling. if (selected.Branch == Branch.Left) { // Shift it outside the range of the subtree of the selected node. if (index - selected.SubTreeSize < positionIndex && positionIndex <= index) { positionIndex += selected.SubTreeSize; } // Shift it past the sibling and the parent of the selected node. if (positionIndex == index + selected.Sibling.SubTreeSize) { positionIndex += 2; } // Shift it past the parent of the selected node. else if (positionIndex == index + selected.Sibling.SubTreeSize + 1) { positionIndex++; } } else { // Shift it past the sibling of the selected node. if (positionIndex == index - selected.SubTreeSize) { positionIndex++; } // Shift it past the parent and outside the range of the subtree of the selected node. if (index - selected.SubTreeSize < positionIndex && positionIndex <= index + 1) { positionIndex += selected.SubTreeSize + 1; } } DecompositionNode sibling = tree.Find(positionIndex); return(new MoveOperation(tree, selected, sibling)); }
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); }
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); }
protected DecompositionNode backtrack(DecompositionTree tree, DecompositionNode[] leaves, double[,] width, BitSet[,] sets, int index, int size, ref int treeindex) { if (size == 1) { DecompositionNode node = new DecompositionNode(leaves[index], tree); node.Index = index; tree.Nodes[index] = node; return(node); } DecompositionNode parent = new DecompositionNode(sets[index, size], treeindex--, tree); tree.Nodes[parent.Index] = parent; int split = -1; double splitwidth = double.PositiveInfinity; for (int i = index + 1; i < index + size; i++) { double max = Math.Max(width[index, i - index], width[i, size - (i - index)]); if (max <= splitwidth) { splitwidth = max; split = i; } } DecompositionNode left = this.backtrack(tree, leaves, width, sets, index, split - index, ref treeindex); DecompositionNode right = this.backtrack(tree, leaves, width, sets, split, size - (split - index), ref treeindex); tree.Attach(parent, left, Branch.Left); tree.Attach(parent, right, Branch.Right); tree.Attach(null, parent, Branch.Left); parent.UpdateWidthProperties(false); return(parent); }
private void updateTree(DecompositionNode a, DecompositionNode b) { DecompositionNode oldParentA = a.Parent; Branch oldBranchA = a.Branch; DecompositionNode oldParentB = b.Parent; Branch oldBranchB = b.Branch; // Find the first common ancestor of a and b. DecompositionNode common = this.findCommonAncestor(a, b); // Swap position of the subtrees. this.Tree.Attach(oldParentA, b, oldBranchA); this.Tree.Attach(oldParentB, a, oldBranchB); // Update the ancestors of a up to the common ancestor. this.updateAncestors(a, common, a.Set, b.Set); // Update the ancestors of b up to the common ancestor. this.updateAncestors(b, common, b.Set, a.Set); // Update the first common ancestor. common.UpdateWidthProperties(false); // Update the remaining common ancestors. this.updateAncestors(common, null, null, null); }
/// <summary> /// Adds the vertex as leaf to the partial tree. /// </summary> /// <param name="tree">The partial tree.</param> /// <param name="vertex">The vertex that will be added.</param> /// <param name="index">The index of the vertex in the tree.</param> protected void add(DecompositionTree tree, Vertex vertex, int index) { // Create the child node. DecompositionNode child = new DecompositionNode(vertex, index, tree); tree.Nodes[index] = child; if (tree.Root == null) { tree.Attach(null, child, Branch.Left); } else { BitSet set = new BitSet(tree.Root.Set); set[vertex.Index] = true; DecompositionNode parent = new DecompositionNode(set, index + 1, tree); tree.Nodes[index + 1] = parent; tree.Attach(parent, tree.Root, Branch.Right); tree.Attach(parent, child, Branch.Left); tree.Attach(null, parent, Branch.Left); parent.UpdateWidthProperties(false); } }
public override IEnumerable <LocalSearchOperation> Operations(DecompositionTree tree, Random rng) { int[] combinationcounters = new int[tree.Nodes.Length]; DecompositionNode[] leftcandidates = new DecompositionNode[tree.Nodes.Length]; DecompositionNode[][] rightcandidates = new DecompositionNode[tree.Nodes.Length][]; DecompositionNode left = null, right = null; int leftindex = 0, total = 0; foreach (var node in tree.Root.SubTree(TreeTraversal.ParentFirst)) { leftcandidates[leftindex] = node; combinationcounters[leftindex] = tree.Nodes.Length - node.SubTreeSize - 1; for (DecompositionNode ancestor = node.Parent; ancestor != null; ancestor = ancestor.Parent) { combinationcounters[leftindex]--; } total += combinationcounters[leftindex]; leftindex++; } int maximum = tree.Nodes.Length; // As long as there is a operation possible while (total > 0) { int sample = rng.Next(total) + 1, sum = 0; // Find a random left candidate. for (leftindex = 0; leftindex < maximum; leftindex++) { // Move invalid left candidates to the back. while (combinationcounters[leftindex] == 0) { maximum--; combinationcounters[leftindex] = combinationcounters[maximum]; leftcandidates[leftindex] = leftcandidates[maximum]; rightcandidates[leftindex] = rightcandidates[maximum]; if (maximum == leftindex) { break; } } sum += combinationcounters[leftindex]; if (sample <= sum) { if (combinationcounters[leftindex] == 0) { throw new InvalidOperationException(); } // Select the random left candidate. left = leftcandidates[leftindex]; DecompositionNode[] candidates = rightcandidates[leftindex]; if (candidates == null) { // Initialize the set of all right candidates. candidates = rightcandidates[leftindex] = new DecompositionNode[combinationcounters[leftindex]]; int index = 0; foreach (DecompositionNode node in left.Sibling.SubTree(TreeTraversal.ParentFirst).Skip(1)) { candidates[index++] = node; } for (DecompositionNode ancestor = left.Parent; !ancestor.IsRoot; ancestor = ancestor.Parent) { foreach (DecompositionNode node in ancestor.Sibling.SubTree(TreeTraversal.ParentFirst)) { candidates[index++] = node; } } } // Select a random position. int positionindex = rng.Next(combinationcounters[leftindex]); right = candidates[positionindex]; candidates[positionindex] = candidates[--combinationcounters[leftindex]]; total--; break; } } if (right == null) { throw new InvalidOperationException(); } yield return(new SwapOperation(tree, left, right)); } }
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 MoveOperation(DecompositionTree tree, DecompositionNode node, DecompositionNode sibling) : base(tree) { this.SelectedNode = node; this.SelectedSibling = sibling; this.OriginalSibling = node.Sibling; }
public SwapOperation(DecompositionTree tree, DecompositionNode left, DecompositionNode right) : base(tree) { this.SelectedNodeLeft = left; this.SelectedNodeRight = right; }
protected override double computeCost() { double maximum = this.SelectedNode.SubTreeWidth, sum = this.SelectedNode.SubTreeSum, topwidth = this.Tree.Root.Right.Width; DecompositionNode common = null; if (!this.SelectedNode.Parent.Set.Intersects(this.SelectedSibling.Set)) { maximum = Math.Max(maximum, Math.Max(this.SelectedSibling.SubTreeWidth, this.OriginalSibling.SubTreeWidth)); sum += this.SelectedSibling.SubTreeSum + this.OriginalSibling.SubTreeSum; // parent double width = this.Tree.WidthParameter.GetWidth(this.Tree.Graph, this.SelectedNode.Set | this.SelectedSibling.Set); sum += width; if (width > maximum) { maximum = width; } // the common ancestor common = this.findCommonAncestor(this.SelectedNode.Parent, this.SelectedSibling); sum += common.Width; if (maximum < common.Width) { maximum = common.Width; } // update the width of the child of the root if (common.IsRoot) { BitSet set = this.Tree.Root.Right.Set; if (set.IsSupersetOf(this.SelectedNode.Set)) { set -= this.SelectedNode.Set; } else { set |= this.SelectedNode.Set; } topwidth = this.Tree.WidthParameter.GetWidth(this.Tree.Graph, set); } // ancestors of parent this.computeWidthAncestors(this.SelectedNode.Parent, common, null, this.SelectedNode.Set, ref maximum, ref sum); // ancestors of the new sibling this.computeWidthAncestors(this.SelectedSibling, common, this.SelectedNode.Set, null, ref maximum, ref sum); } else if (this.SelectedNode.Set.IsSubsetOf(this.SelectedSibling.Set)) { sum += this.OriginalSibling.SubTreeSum; if (maximum < this.OriginalSibling.SubTreeWidth) { maximum = this.OriginalSibling.SubTreeWidth; } // parent sum += this.SelectedSibling.Width; if (maximum < this.SelectedSibling.Width) { maximum = this.SelectedSibling.Width; } // the common ancestor common = this.SelectedSibling; // update the width of the child of the root. if (this.SelectedSibling.IsRoot) { topwidth = this.SelectedNode.Width; } // ancestors of parent this.computeWidthAncestors(this.SelectedNode.Parent, this.SelectedSibling.Parent, null, this.SelectedNode.Set, ref maximum, ref sum); } else // the new sibling is a descendant of the original sibling { sum += this.SelectedSibling.SubTreeSum; if (maximum < this.SelectedSibling.SubTreeWidth) { maximum = this.SelectedSibling.SubTreeWidth; } // parent double width = this.Tree.WidthParameter.GetWidth(this.Tree.Graph, this.SelectedNode.Set | this.SelectedSibling.Set); sum += width; if (maximum < width) { maximum = width; } // the common ancestor common = this.SelectedNode.Parent; // update the width of the child of the root. if (this.SelectedNode.Parent.IsRoot) { topwidth = this.OriginalSibling.Right.Set.IsSupersetOf(this.SelectedSibling.Set) ? this.OriginalSibling.Left.Width : this.OriginalSibling.Right.Width; } // ancestors of the new sibling this.computeWidthAncestors(this.SelectedSibling, this.SelectedNode.Parent, this.SelectedNode.Set, null, ref maximum, ref sum); } // common ancestors this.computeWidthAncestors(common, null, null, null, ref maximum, ref sum); return(DecompositionTree.ComputeCost(maximum, this.Tree.VertexCount, sum, topwidth)); }
// Get all operations in random order. public override IEnumerable <LocalSearchOperation> Operations(DecompositionTree tree, Random rng) { // Initialize the insertion candidate list int[] candidatecounters = new int[tree.Nodes.Length]; DecompositionNode[] insertioncandidates = new DecompositionNode[tree.Nodes.Length]; DecompositionNode[][] positioncandidates = new DecompositionNode[tree.Nodes.Length][]; DecompositionNode insertioncandidate = null, positioncandidate = null; int candidateindex = 0, total = 0; foreach (var node in tree.Root.SubTree(TreeTraversal.ParentFirst)) { insertioncandidates[candidateindex] = node; total += candidatecounters[candidateindex] = tree.Nodes.Length - node.SubTreeSize - 2; candidateindex++; } int maximum = tree.Nodes.Length; // As long as there is a operation possible while (total > 0) { int sample = rng.Next(total) + 1, sum = 0; // Find a random insertion candidate. for (candidateindex = 0; candidateindex < maximum; candidateindex++) { // Move invalid insertion candidates to the back. while (candidatecounters[candidateindex] == 0) { maximum--; candidatecounters[candidateindex] = candidatecounters[maximum]; insertioncandidates[candidateindex] = insertioncandidates[maximum]; positioncandidates[candidateindex] = positioncandidates[maximum]; if (maximum == candidateindex) { break; } } sum += candidatecounters[candidateindex]; if (sample <= sum) { if (candidatecounters[candidateindex] == 0) { throw new InvalidOperationException(); } // Select the random insertion candidate. insertioncandidate = insertioncandidates[candidateindex]; DecompositionNode[] positions = positioncandidates[candidateindex]; if (positions == null) { // Initialize the set of all candidate positions. positions = positioncandidates[candidateindex] = new DecompositionNode[candidatecounters[candidateindex]]; int index = 0; foreach (var node in insertioncandidate.Sibling.SubTree(TreeTraversal.ParentFirst).Skip(1)) { positions[index++] = node; } for (DecompositionNode ancestor = insertioncandidate.Parent; !ancestor.IsRoot; ancestor = ancestor.Parent) { foreach (DecompositionNode node in ancestor.Sibling.SubTree(TreeTraversal.ParentFirst)) { positions[index++] = node; } if (ancestor != insertioncandidate.Parent) { positions[index++] = ancestor; } } if (!insertioncandidate.Parent.IsRoot) { positions[index++] = tree.Root; } } // Select a random position. int positionindex = rng.Next(candidatecounters[candidateindex]); positioncandidate = positions[positionindex]; positions[positionindex] = positions[--candidatecounters[candidateindex]]; total--; break; } } if (positioncandidate == null) { throw new InvalidOperationException(); } yield return(new MoveOperation(tree, insertioncandidate, positioncandidate)); } }
private void updateTree(DecompositionNode oldsibling, DecompositionNode newsibling) { DecompositionNode grandparent = this.SelectedNode.Parent.Parent; Branch parentbranch = this.SelectedNode.Parent.Branch; // connect parent to parent of new sibling this.Tree.Attach(newsibling.Parent, this.SelectedNode.Parent, newsibling.Branch); // connect new sibling to parent this.Tree.Attach(this.SelectedNode.Parent, newsibling, oldsibling.Branch); // connect old sibling to grandparent this.Tree.Attach(grandparent, oldsibling, parentbranch); // update the sets and width properties DecompositionNode common = null; if (!this.SelectedNode.Parent.Set.Intersects(newsibling.Set)) { // parent this.SelectedNode.Parent.Set = this.SelectedNode.Set | newsibling.Set; this.SelectedNode.Parent.UpdateWidthProperties(); // the common ancestor common = this.findCommonAncestor(this.SelectedNode.Parent, oldsibling.Parent); // ancestors of parent this.updateAncestors(this.SelectedNode.Parent, common, this.SelectedNode.Set, null); // ancestors of the old sibling this.updateAncestors(oldsibling, common, null, this.SelectedNode.Set); common.UpdateWidthProperties(false); } else if (this.SelectedNode.Set.IsSubsetOf(newsibling.Set)) { // the common ancestor common = this.SelectedNode.Parent; // ancestors of oldsibling this.updateAncestors(oldsibling, common, null, this.SelectedNode.Set); // parent this.SelectedNode.Parent.Set = this.SelectedNode.Set | newsibling.Set; this.SelectedNode.Parent.UpdateWidthProperties(); } else // the new sibling is a descendant of the original sibling { // parent this.SelectedNode.Parent.Set = this.SelectedNode.Set | newsibling.Set; this.SelectedNode.Parent.UpdateWidthProperties(); // the common ancestor common = oldsibling.Parent; // ancestors of the new sibling this.updateAncestors(this.SelectedNode.Parent, common, this.SelectedNode.Set, null); if (common != null) { common.UpdateWidthProperties(false); } } this.updateAncestors(common, null, null, null); }