internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); int firstArgument = (OpCode != OpCode.NewObj && !Method.IsStatic) ? 1 : 0; Debug.Assert(Method.Parameters.Count + firstArgument == Arguments.Count); Debug.Assert(Method.Parameters.Count + firstArgument == ArgumentToParameterMap.Length); if (firstArgument == 1) { Debug.Assert(Arguments[0].ResultType == ExpectedTypeForThisPointer(ConstrainedTo ?? Method.DeclaringType), $"Stack type mismatch in 'this' argument in call to {Method.Name}()"); Debug.Assert(ArgumentToParameterMap[0] == -1, "'this' argument must always be mapped at position 0"); } int paramCount = Method.Parameters.Count; if (paramCount > 0) { BitSet bitSet = new BitSet(paramCount); for (int i = 0; i < paramCount; ++i) { int mappedTo = ArgumentToParameterMap[firstArgument + i]; Debug.Assert(mappedTo >= 0 && mappedTo < paramCount, $"mapping out of [0..{paramCount}[, was: {mappedTo}"); Debug.Assert(!bitSet[mappedTo], $"argument {mappedTo} is already mapped to a different parameter"); bitSet.Set(mappedTo); Debug.Assert(Arguments[firstArgument + i].ResultType == Method.Parameters[mappedTo].Type.GetStackType(), $"Stack type mismatch in parameter {mappedTo} (argument {firstArgument + i}) in call to {Method.Name}()"); } Debug.Assert(bitSet.All(0, paramCount - 1), "Not all arguments are mapped to a parameter"); } }
public void AllInRange() { var bitset = new BitSet(300); bitset.Set(1, 299); Assert.IsTrue(bitset.All(1, 299)); Assert.IsTrue(bitset.All(10, 290)); Assert.IsTrue(bitset.All(100, 200)); Assert.IsFalse(bitset.All(0, 200)); Assert.IsFalse(bitset.All(0, 1)); Assert.IsFalse(bitset.All(1, 300)); bitset[200] = false; Assert.IsFalse(bitset.All(1, 299)); }
/// <summary> /// Tests if the graph can be separated with a safe separator of size 2. If so, the separator is saved in the "separator" member variable /// </summary> /// <returns>true iff a size 2 separator exists</returns> public bool FindSize2Separator() { BitSet notIgnoredVertices = BitSet.All(graph.vertexCount); // loop over every pair of vertices for (int u = 0; u < graph.vertexCount; u++) { notIgnoredVertices[u] = false; foreach (int a in ArticulationPoints(graph, notIgnoredVertices)) { separator = new BitSet(graph.vertexCount); separator[u] = true; separator[a] = true; separatorType = SeparatorType.Size2; return(true); } notIgnoredVertices[u] = true; } return(false); }
/// <summary> /// lists all articulation points of the graph /// This method can also be used to test for separators of size n by passing a set of n-1 vertices as /// ignoredVertices. and combining the result with the ignoredVertices. /// Code adapated from https://slideplayer.com/slide/12811727/ /// </summary> /// <param name="availableVertices">a list of vertices to treat as existent</param> /// <returns>an iterator over all articulation points</returns> public static IEnumerable <int> ArticulationPoints(Graph graph, BitSet availableVertices = null) { if (graph.vertexCount == 0) // exit early if there are no vertices { yield break; } availableVertices = availableVertices ?? BitSet.All(graph.vertexCount); // create an empty list if the given one is null in order to prevent NullReferenceExceptions int start = availableVertices.First(); int[] count = new int[graph.vertexCount]; // TODO: make member variable int[] reachBack = new int[graph.vertexCount]; // TODO: make member variable Queue <int>[] children = new Queue <int> [graph.vertexCount]; // TODO: make member variable for (int i = 0; i < graph.vertexCount; i++) { count[i] = int.MaxValue; reachBack[i] = int.MaxValue; children[i] = new Queue <int>(); } count[start] = 0; int numSubtrees = 0; for (int i = 0; i < graph.adjacencyList[start].Count; i++) { int rootNeighbor = graph.adjacencyList[start][i]; if (count[rootNeighbor] == int.MaxValue && availableVertices[rootNeighbor]) { Stack <(int, int, int)> stack = new Stack <(int, int, int)>(); stack.Push((rootNeighbor, 1, start)); while (stack.Count > 0) { (int node, int timer, int fromNode) = stack.Peek(); if (count[node] == int.MaxValue) { count[node] = timer; reachBack[node] = timer; List <int> neighbors = graph.adjacencyList[node]; for (int j = 0; j < neighbors.Count; j++) { int neighbor = neighbors[j]; if (neighbor != fromNode && availableVertices[neighbor]) { children[node].Enqueue(neighbor); } } } else if (children[node].Count > 0) { int child = children[node].Dequeue(); if (count[child] < int.MaxValue) { if (reachBack[node] > count[child]) { reachBack[node] = count[child]; } } else { stack.Push((child, timer + 1, node)); } } else { if (node != rootNeighbor) { if (reachBack[node] >= count[fromNode]) { yield return(fromNode); } if (reachBack[fromNode] > reachBack[node]) { reachBack[fromNode] = reachBack[node]; } } stack.Pop(); } } numSubtrees++; } } if (numSubtrees > 1) { yield return(start); } }
/// <summary> /// finds candidate safe separators using a heuristic. This is Tamaki's code. /// </summary> /// <param name="mode"></param> /// <returns></returns> public static List <BitSet> Tamaki_HeuristicVerticesAndNeighbors(Graph graph, Heuristic mode) { // code adapted from https://github.com/TCS-Meiji/PACE2017-TrackA/blob/master/tw/exact/GreedyDecomposer.java List <BitSet> separators = new List <BitSet>(); // ----- lines 62 to 64 ----- // copy fields so that we can change them locally Graph copy = new Graph(graph); List <BitSet> frontier = new List <BitSet>(); BitSet remaining = BitSet.All(graph.vertexCount); // ----- lines 66 to 80 ----- while (!remaining.IsEmpty()) { // ----- lines 67 to 80 ----- int vmin = FindMinCostVertex(remaining, copy, mode); // ----- line 82 ----- List <BitSet> joined = new List <BitSet>(); // lines 84 and 85 ----- BitSet toBeAclique = new BitSet(graph.vertexCount); toBeAclique[vmin] = true; // ----- lines 87 to 93 ----- foreach (BitSet s in frontier) { if (s[vmin]) { joined.Add(s); toBeAclique.UnionWith(s); } } // ----- lines 97 to 119 ----- if (joined.Count == 0) { toBeAclique[vmin] = true; } else if (joined.Count == 1) { BitSet uniqueSeparator = joined[0]; BitSet test = new BitSet(copy.openNeighborhood[vmin]); test.IntersectWith(remaining); if (uniqueSeparator.IsSupersetOf(test)) { uniqueSeparator[vmin] = false; if (uniqueSeparator.IsEmpty()) { separators.Remove(uniqueSeparator); frontier.Remove(uniqueSeparator); } remaining[vmin] = false; continue; } } // ----- line 121 ----- BitSet temp = new BitSet(copy.openNeighborhood[vmin]); temp.IntersectWith(remaining); toBeAclique.UnionWith(temp); // ----- line 129 ----- copy.MakeIntoClique(toBeAclique.Elements()); // ----- lines 131 and 132 ----- BitSet sep = new BitSet(toBeAclique); sep[vmin] = false; // ----- lines 134 to 147 ----- if (!sep.IsEmpty()) { BitSet separator = new BitSet(sep); separators.Add(separator); frontier.Add(separator); } // ----- lines 153 to 161 ----- foreach (BitSet s in joined) { Debug.Assert(!s.IsEmpty()); frontier.Remove(s); } remaining[vmin] = false; } return(separators); }