// Counts the number of independent sets in a graph, such that: // - The vertices in P are legal choices for our IS, initially set to all vertices in the graph // - None of the vertices in X are used, initially empty // The performDFS boolean is used to check if we should perform a check for connectedness on this level of the recursion private static long Compute(Graph graph, BitSet p, BitSet x, bool performDfs) { // Base case, when P and X are both empty we cannot expand the IS if (p.IsEmpty && x.IsEmpty) return 1; // Base case, if a vertex w in X has no neighbor in P, then it means that this IS will never get maximal // since we could always include w. Thus, the IS will not be valid and we return 0. foreach (int w in x) if ((graph.OpenNeighborhood(w) * p).IsEmpty) return 0; long count = 0; // If a DFS is needed we check if the graph induced by (P + X) is still connected. // If the graph is disconnected, in components c1,...,cn then we can simply count the IS of all these components // after which we simply multiply these numbers. if (performDfs) { if (!DepthFirstSearch.Connected(graph, p + x)) { count = 1; foreach (BitSet component in DepthFirstSearch.ConnectedComponents(graph, p + x)) count *= Compute(graph, component * p, component * x, false); return count; } } // Select a pivot in P to branch on // In this case we pick the vertex with the largest degree int maxDegree = -1; ; int pivot = -1; foreach (int u in p) { int deg = graph.Degree(u); if (deg > maxDegree) { maxDegree = deg; pivot = u; } } // There should always be a pivot after the selection procedure if (pivot == -1) throw new Exception("Pivot has not been selected"); // We branch on the pivot, one branch we include the pivot in the IS. // This might possibly disconnect the subgraph G(P + X), thus we set the performDFS boolean to true. count = Compute(graph, p - graph.ClosedNeighborhood(pivot), x - graph.OpenNeighborhood(pivot), true); // One branch we exclude the pivot of the IS. This will not cause the graph to get possibly disconnected count += Compute(graph, p - pivot, x + pivot, false); return count; }
public static Decomposition Compute(Graph graph, Func<Graph, LinearDecomposition> decomposer, params IReductionRule[] rules) { Graph clone = graph.Clone(); IReductionRuleCommand[] commands = GraphPreprocessor.ApplyRules(clone, rules).Reverse().ToArray(); LinearDecomposition ld = decomposer(clone); Decomposition dec = Decomposition.FromLinearDecomposition(ld); Tree tree = commands.Aggregate(dec.Tree, (current, command) => command.Expand(current)); return new Decomposition(graph, tree); }
public IEnumerable<IReductionRuleCommand> Find(Graph graph) { foreach (int vertex in graph.Vertices) { if (graph.Degree(vertex) == 0) { graph.RemoveVertex(vertex); yield return new Command(vertex); } } }
public IEnumerable<IReductionRuleCommand> Find(Graph graph) { foreach (int vertex in graph.Vertices) { // TODO: Count is not O(1) if (graph.Degree(vertex) == 1 && graph.Vertices.Count > 1) { BitSet connection = graph.OpenNeighborhood(vertex); graph.RemoveVertex(vertex); yield return new Command(vertex, connection); } } }
// 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) { Vector = vector; _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); } }
// This constructor returns a new bipartite graph by putting all vertices in 'left' on one side, and 'right' on the other side // There will be an edge between two vertices if there was an edge in the original graph public BipartiteGraph(Graph graph, BitSet left, BitSet right) : this(left, right, left.Count + right.Count) { Dictionary<int, int> mapping = new Dictionary<int, int>(); int i = 0; foreach (int v in Left + Right) mapping[v] = i++; foreach (int v in Left) foreach (int w in graph.OpenNeighborhood(v) * Right) Connect(mapping[v], mapping[w]); }
public Graph(Graph graph) { Vertices = graph.Vertices; _adjacencyMatrix = new BitSet[graph.Size]; Size = graph.Size; for (int i = 0; i < Size; i++) { _adjacencyMatrix[i] = graph._adjacencyMatrix[i]; } }
// Given a vertex w, we can update the dNeighborhood of a set X to reflect the dNeighborhood of the set X + w in O(n) time public DNeighborhood CopyAndUpdate(Graph graph, int w) { // initialize an empty dNeighborhood in O(|Vector|) time DNeighborhood nx = new DNeighborhood(Vector); // Copy all values in O(|Vector|) time foreach (int v in Vector) nx._occurrences[v] = _occurrences[v]; // Foreach vertex in N(w) * Vector they will appear one extra time in the multiset // This operation take O(n) time because of the bitset operation foreach (int v in graph.OpenNeighborhood(w) * Vector) nx._occurrences[v] = Math.Min(dValue, nx._occurrences[v] + 1); return nx; }
public static IEnumerable<IReductionRuleCommand> ApplyRules(Graph graph, params IReductionRule[] rules) { bool found; do { found = false; foreach (IReductionRule rule in rules) { foreach (IReductionRuleCommand command in rule.Find(graph)) { found = true; yield return command; } } } while (found); }
// 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; // 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 -= v; x += v; } return count; }
public IEnumerable<IReductionRuleCommand> Find(Graph graph) { foreach (int v in graph.Vertices) { foreach (int u in graph.Vertices) { if (v == u) { break; } // TODO: Count is not O(1) if (graph.Vertices.Count > 1 && ((graph.OpenNeighborhood(v) - u).Equals(graph.OpenNeighborhood(u) - v))) { graph.RemoveVertex(v); yield return new Command(v, u); break; } } } }
// 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 long 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; long count = 0; int pivot = -1; int min = int.MaxValue; // Procedure to find a pivot // The idea is that in any maximal IS, either vertex u or a neighbor of u is included (else we could expand by adding u to the IS) // We find the u with the smallest neighborhood, so that we will keep the number of branches low foreach (int u in (p + x)) { int size = (p * graph.OpenNeighborhood(u)).Count; if (size < min) { min = size; pivot = u; } } // There should always be a pivot after the selection procedure, else P and X should both have been empty if (pivot == -1) throw new Exception("Pivot has not been selected"); // Foreach vertex v in the set containing the legal choices of the the closed neighborhood of the pivot, // we include each choice in the IS and compute how many maximal IS will include v by going into recursion foreach (int v in (p * graph.ClosedNeighborhood(pivot))) { count += Compute(graph, r + v, p - graph.ClosedNeighborhood(v), x - graph.OpenNeighborhood(v)); p -=v; x += v; } return count; }
/*************************/ // Constructor /*************************/ // Basic constructor public GenericSolver(Decomposition decomposition) { // The graph and binary decomposition tree that we are working on _graph = decomposition.Graph; _tree = decomposition.Tree; }
public static IEnumerable<BooleanChain> FromGraph(Graph graph, BitSet bitSet) { foreach (int vertex in bitSet) { yield return new BooleanChain(graph, vertex); } }
// Initial call public static long Compute(Graph graph) { return Compute(graph, new BitSet(0, graph.Size), graph.Vertices, new BitSet(0, graph.Size)); }
// Parses a file of DGF format, from which we can build a graph public static Graph Read(TextReader reader) { string line; int nVertices = 0; // First we parse the number of vertices while ((line = reader.ReadLine()) != null) { // Skip everything until we find the first useful line if (!line.StartsWith("p ")) continue; // First line always reads 'p edges {n} {e}' string[] def = line.Split(); nVertices = int.Parse(def[2]); // number of vertices break; } // Initialize the graph Graph graph = new Graph(nVertices); Dictionary<int, int> identifiers = new Dictionary<int, int>(); int counter = 0; bool renamed = false; while ((line = reader.ReadLine()) != null) { // Skip comments if (line.StartsWith("c ")) continue; // If a line starts with an n it means we do not work with integers [1,...,n], but we use an arbitrary set of integers // This means we need to keep track of which edges we should create internally, since we use [0,...,n) if (line.StartsWith("n ")) { renamed = true; string[] node = line.Split(); int id = int.Parse(node[1]); // actual identifier identifiers[id] = counter++; // counter will be the internal identifier } // Parsing of the edges if (line.StartsWith("e ")) { string[] edge = line.Split(' '); int i = int.Parse(edge[1]); int j = int.Parse(edge[2]); // If there were arbitrary numbers used, look them up to find what we will use internally if (renamed) { i = identifiers[i]; j = identifiers[j]; } // If no other identifiers are given, we have only have to an element // DGF files use the range [1...n], while internally we use [0...n), thus a simple minus 1 will suffice else { i--; j--; } // Create the edge graph.Connect(i, j); } } return graph; }
public BooleanChain(Graph graph, int vertex) { this.Graph = graph; this.Vertex = vertex; this.CalculateBooleanWidth(); }