// Builds a neighborhood for a set X from the ground on up, without relying on what has been saved previously in O(n^2) time public dNeighborhood(BitSet X, BitSet vector, Graph graph) { // O(n) time copy Vector = vector.Copy(); Occurrences = new Dictionary<int, int>(); // Loops in O(|Vector|) time over all vertices in the vector foreach (int v in Vector) { // Bitset operation of O(n) time BitSet nv = graph.OpenNeighborhood(v) * X; Occurrences[v] = Math.Min(nv.Count, dValue); } }
// Returns all connected components in a certain subgraph, where we define a subgraph by the vertices that are contained in it // We apply multiple dfs searches to find all connected parts of the graph public static List<BitSet> ConnectedComponents(Graph graph, BitSet subgraph) { // Each connected component is defined as a bitset, thus the result is a list of these bitsets List<BitSet> result = new List<BitSet>(); // Working stack for the dfs algorithm Stack<int> stack = new Stack<int>(); // Each vertex of the subgraph will either be explored, or it will be the starting point of a new dfs search BitSet todo = subgraph.Copy(); while (!todo.IsEmpty) { int s = todo.First(); stack.Push(s); // Start tracking the new component BitSet component = new BitSet(0, graph.Size); // Default dfs exploring part of the graph while (stack.Count > 0) { int v = stack.Pop(); // If we have not encountered this vertex before (meaning it isn't in this component), then we check for all neighbors if they are part of the subgraph // If a neighbor is part of the subgraph it means that we have to push it on the stack to explore it at a later stage for this component if (!component.Contains(v)) { component.Add(v); // Remove this vertex from the 'todo' list, since it can never be the starting point of a new component todo.Remove(v); foreach (int w in graph.OpenNeighborhood(v)) if (subgraph.Contains(w)) stack.Push(w); } } // The whole connected component has been found, so we can add it to the list of results result.Add(component); } return result; }
// Counts the number of independent sets in a graph, such that: // - All vertices in R are included in the independent set, initially empty // - Some of the vertices in P are included in the independent set, initially all vertices of the graph // - None of the vertices in X are included in the independent set, initially empty private static int Compute(Graph graph, BitSet R, BitSet P, BitSet X) { // Base case, when P and X are both empty we cannot expand the IS if (P.IsEmpty && X.IsEmpty) return 1; int count = 0; BitSet copy = P.Copy(); // Foreach vertex v in P we include it in the IS and compute how many maximal IS will include v by going into recursion. foreach (int v in copy) { count += Compute(graph, R + v, P - graph.ClosedNeighborhood(v), X - graph.OpenNeighborhood(v)); P.Remove(v); X.Add(v); } return count; }
/*************************/ // Candidate strategy /*************************/ public static BitSet Candidates(Graph graph, BitSet left, BitSet right, CandidateStrategy candidateStrategy) { BitSet nl = graph.Neighborhood(left) * right; return candidateStrategy == CandidateStrategy.All ? right.Copy() : (nl + graph.Neighborhood(nl)) * right; }
private void FillTable(Graph graph, List<int> sequence) { int n = graph.Size; // Processed vertices BitSet left = new BitSet(0, n); // Unprocessed vertices BitSet right = graph.Vertices; // Lists of representatives that we keep track of on each level of the algorithm LinearRepresentativeList reps = new LinearRepresentativeList(); // Initial insertions, the empty set always has the empty neighborhood set as a representative initially reps.Update(new BitSet(0, n), new BitSet(0, n)); for (int i = 0; i < sequence.Count; i++) { /// We give v the possibility to be a representative instead of being contained in neighborhoods int v = sequence[i]; // Actually move v from one set to the other set left.Add(v); right.Remove(v); // We don't want to disturb any pointers so we create new empty datastructures to save everything for the next iteration LinearRepresentativeList nextReps = new LinearRepresentativeList(); // We are iterating over all representatives saved inside the list of the previous step. For each entry there are only two possibilities to create a new neighborhood foreach (BitSet representative in reps) { // Case 1: The neighborhood possibly contained v (thus v has to be removed), but is still valid BitSet neighborhood = reps.GetNeighborhood(representative) - v; nextReps.Update(representative, neighborhood); // Case 2: The union of the old neighborhood, together with v's neighborhood, creates a new entry. The representative is uniond together with v and saved. BitSet representative_ = representative + v; BitSet neighborhood_ = neighborhood + (graph.OpenNeighborhood(v) * right); nextReps.Update(representative_, neighborhood_); } // Update the values for the next iteration reps = nextReps; // Save the maximum size that we encounter during all iterations; this will be the boolean dimension of the graph. MaxDimension = Math.Max(MaxDimension, reps.Count); // Save the representatives at the current cut in the table Table[left.Copy()] = reps; } }
public int this[BitSet representative, int k] { get { if (!Data[k].ContainsKey(representative)) return 0; return Data[k][representative]; } set { Data[k][representative.Copy()] = value; } }
/*************************/ // Basic operations /*************************/ // When adding a new entry we check if the neighborhood is already contained in the set // If true, then we might replace the previous representative that is not connected to this neighborhood if the new one is lexicographically smaller public void Update(BitSet representative, dNeighborhood neighborhood) { Map.Add(representative.Copy(), neighborhood); }
/*************************/ // Basic operations /*************************/ // When adding a new entry we check if the neighborhood is already contained in the set // If true, then we might replace the previous representative that is not connected to this neighborhood if the new one is lexicographically smaller public void Update(BitSet representative, BitSet neighborhood) { if (Map.ContainsValue(neighborhood)) { BitSet previousRep = Map.Reverse[neighborhood]; if (representative.IsLexicographicallySmaller(previousRep)) { Map.Remove(previousRep, neighborhood); Map.Add(representative.Copy(), neighborhood.Copy()); } } else { Map.Add(representative.Copy(), neighborhood.Copy()); } }
// Basic constructor private BipartiteGraph(BitSet _left, BitSet _right, int size) : base(size) { left = _left.Copy(); right = _right.Copy(); }
public int this[BitSet inner, BitSet outer, int k] { get { Tuple<BitSet, BitSet> t = new Tuple<BitSet, BitSet>(inner, outer); if (!Data[k].ContainsKey(t)) return 0; return Data[k][t]; } set { Tuple<BitSet, BitSet> t = new Tuple<BitSet, BitSet>(inner.Copy(), outer.Copy()); Data[k][t] = value; } }
// Implementation of Algorithm 1 of 'Fast dynamic programming for locally checkable vertex subset and vertex partitioning problems' (Bui-Xuan et al.) // Used to compute the representatives and their corresponding dNeighborhoods for a given node of the decomposition tree private void FillTable(Graph graph, BitSet cut) { int n = graph.Size; BitSet _cut = graph.Vertices - cut; // Lists of representatives that we keep track of on each level of the algorithm RepresentativeList representatives = new RepresentativeList(); RepresentativeList lastLevel = new RepresentativeList(); // Initial insertions, the empty set always has the empty neighborhood set as a representative initially dNeighborhood dInitial = new dNeighborhood(_cut); representatives.Update(new BitSet(0, n), dInitial); lastLevel.Update(new BitSet(0, n), dInitial); while (lastLevel.Count > 0) { RepresentativeList nextLevel = new RepresentativeList(); foreach (BitSet r in lastLevel) { foreach (int v in cut) { // avoid that r_ = r, since we already saved all sets of that size if (r.Contains(v)) continue; BitSet r_ = r + v; dNeighborhood dn = representatives.GetNeighborhood(r).CopyAndUpdate(graph, v); if (!representatives.ContainsNeighborhood(dn) && !dn.Equals(representatives.GetNeighborhood(r))) { nextLevel.Update(r_, dn); representatives.Update(r_, dn); } } } // Update the values for the next iteration lastLevel = nextLevel; } // Save the representatives at the current cut in the table Table[cut.Copy()] = representatives; // Save the maximum size that we encounter during all iterations; this will be the boolean dimension of the graph is d = 1. MaxDimension = Math.Max(MaxDimension, representatives.Count); }