public static bool IsPossiblyUsable(List <PTD> children, ImmutableGraph graph) { for (int i = 0; i < children.Count; i++) { PTD child1 = children[i]; for (int j = i + 1; j < children.Count; j++) { PTD child2 = children[j]; BitSet childrenInletsIntersection = new BitSet(child1.inlet); childrenInletsIntersection.IntersectWith(child2.inlet); if (!childrenInletsIntersection.IsEmpty()) { return(false); } BitSet verticesIntersection = new BitSet(child1.vertices); verticesIntersection.IntersectWith(child2.vertices); if (!child1.outlet.IsSupersetOf(verticesIntersection) || !child2.outlet.IsSupersetOf(verticesIntersection)) { return(false); } } } return(true); }
public static PTD ExtendToPMC_Rule2(PTD Tau_wiggle, BitSet vNeighbors, ImmutableGraph graph) { BitSet bag = new BitSet(vNeighbors); List <PTD> children = new List <PTD>(Tau_wiggle.children); BitSet vertices = new BitSet(Tau_wiggle.vertices); vertices.UnionWith(vNeighbors); BitSet outlet = graph.Outlet(bag, vertices); BitSet inlet = new BitSet(vertices); inlet.ExceptWith(outlet); return(new PTD(bag, vertices, outlet, inlet, children)); }
public static PTD ExtendToPMC_Rule3(PTD Tau_wiggle, BitSet newRoot, ImmutableGraph graph) { Debug.Assert(newRoot.IsSupersetOf(Tau_wiggle.Bag)); BitSet bag = newRoot; BitSet vertices = new BitSet(Tau_wiggle.vertices); vertices.UnionWith(newRoot); List <PTD> children = new List <PTD>(Tau_wiggle.children); BitSet outlet = graph.Outlet(bag, vertices); BitSet inlet = new BitSet(vertices); inlet.ExceptWith(outlet); return(new PTD(bag, vertices, outlet, inlet, children)); }
/// <summary> /// asserts that this ptd is actually a tree decomposition for the given graph /// </summary> /// <param name="graph">the graph that this ptd is supposed to be a tree decomposition of</param> public void AssertValidTreeDecomposition(ImmutableGraph graph) { // create a list of all bags List <BitSet> bagsList = new List <BitSet>(); List <int> parentBags = new List <int>(); Stack <PTD> childrenStack = new Stack <PTD>(); Stack <int> parentStack = new Stack <int>(); childrenStack.Push(this); parentStack.Push(-1); while (childrenStack.Count > 0) { PTD current = childrenStack.Pop(); int parent = parentStack.Pop(); bagsList.Add(current.Bag); parentBags.Add(parent); foreach (PTD child in current.children) { childrenStack.Push(child); parentStack.Push(bagsList.Count - 1); } } // check vertex cover for (int i = 0; i < graph.vertexCount; i++) { bool isCovered = false; foreach (BitSet bag in bagsList) { if (bag[i]) { isCovered = true; break; } } if (!isCovered) { Print(); Trace.Fail(String.Format("The printed ptd for graph {0} does not cover all of the graph's vertices. Vertex {1} is not covered.", graph.graphID, i)); } } // check edge cover for (int u = 0; u < graph.vertexCount; u++) { foreach (int v in graph.adjacencyList[u]) { bool isCovered = false; foreach (BitSet bag in bagsList) { if (bag[u] && bag[v]) { isCovered = true; break; } } if (!isCovered) { Print(); Trace.Fail(String.Format("The printed ptd for graph {0} does not cover all of the graph's edges. Edge ({1},{2}) is not covered.", graph.graphID, u, v)); } } } // check consistency for (int i = 0; i < graph.vertexCount; i++) { //if (possiblyUsableIgnore[i]) //{ // continue; //} /* * key insight: all bags containing i form a subtree. * Therefore, in order for the tree decomposition to be consistent, there must be only one root for all subtrees containing i */ HashSet <int> ancestors = new HashSet <int>(); for (int j = 0; j < bagsList.Count; j++) { if (bagsList[j][i] == true) { int currentAncestor = j; int parentBag = parentBags[j]; while (parentBag != -1 && bagsList[parentBag][i]) { currentAncestor = parentBag; parentBag = parentBags[currentAncestor]; ; } ancestors.Add(currentAncestor); if (ancestors.Count == 2) { Print(); Trace.Fail(String.Format("The printed ptd for graph {0} is not consistent. There are at least two subtrees containing vertex {1}.", graph.graphID, i)); } } } } }
/// <summary> /// tests if this PTD is an incoming PTD /// </summary> /// <returns>true iff the PTD is incoming</returns> public bool IsIncoming(ImmutableGraph graph) { BitSet rest = vertices.Complement(); return(inlet.First() < rest.First()); }
/// <summary> /// a method extracted from the method above due to performance reasons. Read it as if the body of the method above would just continue here. /// </summary> /// <param name="Tau_prime">the ptdur</param> /// <param name="Tau">the ptd</param> /// <param name="graph">the underlying graph</param> /// <param name="result">the resulting ptd, or null if the return value is false</param> /// <param name="bag">the bag of the ptd to be</param> /// <returns>true, iff the resulting ptd is possibly usable</returns> private static bool AddPTDToPTDUR_CheckPossiblyUsable_CheckCliquish_Helper(PTD Tau_prime, PTD Tau, ImmutableGraph graph, out PTD result, BitSet bag, uint futureBagSize, int k, Graph mutableGraph) { List <PTD> children = new List <PTD>(Tau_prime.children); children.Add(Tau); // exit early if not possibly usable if (!IsPossiblyUsable(children, graph)) { result = null; return(false); } // if no vertices can be added to the bag due to size and the bag is not a pmc, we can reject this ptd immediately because it is not useful if (futureBagSize == k + 1 && !graph.IsPotMaxClique(bag)) { result = null; return(false); } if (!graph.IsCliquish(bag)) { result = null; return(false); } // if only one vertex can be added, determine all the candidates that would make this bag a pmc when added. If there are none, return. if (testIfAddingOneVertexToBagFormsPMC && futureBagSize == k) { // if bag is pmc already, we need this ptdur. (In that case no candidate exists which could be added.) if (!graph.IsPotMaxClique(bag)) { bool useless = true; foreach ((BitSet component, BitSet neighbor) in graph.ComponentsAndNeighbors(bag)) { // candidates are only found in full components if (neighbor.Equals(bag) && !component.Intersects(Tau_prime.vertices) && !component.Intersects(Tau.vertices)) { if (neighborsFirst) { onlyNeighborStopwatch.Start(); // test if a vertex in the bag has exactly one neighbor in this component, and the bag plus that vertex is still cliquish foreach (int v in bag.Elements()) { BitSet neighbors = new BitSet(graph.openNeighborhood[v]); neighbors.IntersectWith(component); if (neighbors.Count() == 1) { int candidate = neighbors.First(); bag[candidate] = true; if (graph.IsCliquish(bag)) // in this case it is guaranteed that the bag is also a pmc { Debug.Assert(graph.IsPotMaxClique(bag)); bag[candidate] = false; useless = false; break; } bag[candidate] = false; } } onlyNeighborStopwatch.Stop(); if (!useless) { break; } } articulationPointCandidatesStopwatch.Start(); // find articulation points within this component foreach (int articulationPoint in SafeSeparator.ArticulationPoints(mutableGraph, component)) { bag[articulationPoint] = true; if (graph.IsPotMaxClique(bag)) { bag[articulationPoint] = false; useless = false; break; } bag[articulationPoint] = false; } articulationPointCandidatesStopwatch.Stop(); if (!useless) { break; } if (!neighborsFirst) { onlyNeighborStopwatch.Start(); // test if a vertex in the bag has exactly one neighbor in this component, and the bag plus that vertex is still cliquish foreach (int v in bag.Elements()) { BitSet neighbors = new BitSet(graph.openNeighborhood[v]); neighbors.IntersectWith(component); if (neighbors.Count() == 1) { int candidate = neighbors.First(); bag[candidate] = true; if (graph.IsCliquish(bag)) // in this case it is guaranteed that the bag is also a pmc { Debug.Assert(graph.IsPotMaxClique(bag)); bag[candidate] = false; useless = false; break; } bag[candidate] = false; } } onlyNeighborStopwatch.Stop(); if (!useless) { break; } } // TODO: possibly exclude candidates that are in this ptdur's inlet? Is that correct? } } if (useless) { result = null; return(false); } } } // usability is established, so we build the ptd BitSet vertices = new BitSet(Tau_prime.vertices); vertices.UnionWith(Tau.vertices); BitSet outlet = graph.Outlet(bag, vertices); BitSet inlet = new BitSet(vertices); inlet.ExceptWith(outlet); result = new PTD(new BitSet(bag), vertices, outlet, inlet, children); return(true); }
public static bool AddPTDToPTDUR_CheckBagSize_CheckPossiblyUsable_CheckCliquish(PTD Tau_prime, PTD Tau, ImmutableGraph graph, int k, out PTD result, Graph mutableGraph) { // return early if bag would get too big uint futureBagSize = BitSet.CountUnion(Tau_prime.Bag, Tau.outlet); if (futureBagSize > k + 1) { result = null; return(false); } BitSet bag = new BitSet(Tau_prime.Bag); bag.UnionWith(Tau.outlet); return(AddPTDToPTDUR_CheckPossiblyUsable_CheckCliquish_Helper(Tau_prime, Tau, graph, out result, bag, futureBagSize, k, mutableGraph)); }