コード例 #1
0
ファイル: Graph.cs プロジェクト: FrankvH/BooleanWidth
        /*************************/
        // Construction
        /*************************/
        // Constructor for a new graph of size n
        public Graph(int n)
        {
            vertices = new BitSet(0, n);
            AdjacencyMatrix = new BitSet[n];

            Size = n;

            for (int i = 0; i < n; i++)
            {
                vertices.Add(i);
                AdjacencyMatrix[i] = new BitSet(0, n);
            }
        }
コード例 #2
0
ファイル: BronKerbosch.cs プロジェクト: FrankvH/BooleanWidth
        // 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;
        }
コード例 #3
0
ファイル: Parser.cs プロジェクト: FrankvH/BooleanWidth
        // Parses a decomposition given the filename of the decomposition and the graph files.
        public static Decomposition ParseDecomposition(string decompositionFilename, string graphFilename)
        {
            Graph graph = ParseGraph(graphFilename);
            StreamReader sr = new StreamReader(decompositionFilename);
            string line;
            Tree tree = new Tree();

            // Each line is simply an integer, which is the sequence of the linear decomposition
            while ((line = sr.ReadLine()) != null)
            {
                // Skip comments
                if (line.StartsWith("c ")) continue;

                string[] s = line.Trim().Split(' ');
                BitSet node = new BitSet(0, graph.Size);
                foreach (string vertex in s)
                    node.Add(int.Parse(vertex) - 1); // -1 because internally we work with [0,...,n)
                tree.Insert(node);
            }

            return new Decomposition(graph, tree);
        }
コード例 #4
0
ファイル: Tomita.cs プロジェクト: FrankvH/BooleanWidth
        // 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.Remove(v);
                X.Add(v);
            }

            return count;
        }
コード例 #5
0
        // Alternative way of calculating the boolean width of a decomposition by counting the number of maximal independent sets in bipartite graphs,
        // constructed for each cut of the decomposition
        private long CalculateBooleanWidthBiPartite()
        {
            BitSet left = new BitSet(0, Graph.Size);
            BitSet right = Graph.Vertices;
            long max = int.MinValue;

            foreach (int v in Sequence)
            {
                left.Add(v);
                right.Remove(v);
                // Construct the bipartite graph
                BipartiteGraph bg = new BipartiteGraph(Graph, left, right);

                // Count the number of maximal independent sets in this bipartite graph
                max = Math.Max(max, CC_MIS.Compute(bg));
            }
            return max;
        }
コード例 #6
0
        public static int Compute(LinearDecomposition decomposition)
        {
            Graph graph = decomposition.Graph;
            int n = graph.Size;
            List<int> sequence = decomposition.Sequence;
            BitSet left = new BitSet(0, graph.Size);
            BitSet right = graph.Vertices;
            BitSet VG = graph.Vertices;

            LinearRepresentativeTable cuts = new LinearRepresentativeTable(graph, sequence);
            LookupTable table = new LookupTable();

            // first initialize the very first leaf node
            int l = sequence[0];
            left.Add(l);
            right.Remove(l);

            // Base cases
            BitSet leaf = new BitSet(0, n) { l };
            BitSet nleaf = new BitSet(0, n) { graph.OpenNeighborhood(l).First() };

            table[new BitSet(0, n), new BitSet(0, n)] = int.MaxValue;
            table[leaf, new BitSet(0, n)] = 1;
            table[leaf, nleaf] = 1;
            table[new BitSet(0, n), nleaf] = 0;

            for (int i = 1; i < sequence.Count; i++)
            {
                int v = sequence[i];

                left.Add(v);
                right.Remove(v);

                LinearRepresentativeList LRw = cuts[left];
                LinearRepresentativeList LRw_ = cuts[right];

                LinearRepresentativeList LRa = cuts[left - v];
                LinearRepresentativeList LRa_ = cuts[right + v];

                LookupTable newTable = new LookupTable();

                foreach (BitSet outside in LRw_)
                {
                    foreach (BitSet inside in LRa)
                    {
                        BitSet nrw_ = graph.Neighborhood(outside) * (left - v);
                        BitSet ra_ = LRa_.GetRepresentative(nrw_);

                        BitSet nra = graph.Neighborhood(inside) * right;
                        BitSet rw = LRw.GetRepresentative(nra);

                        int savedValue = newTable[rw, outside];
                        int newValue = table[inside, ra_];

                        BitSet raw_ = inside + outside;
                        BitSet nraw_ = graph.Neighborhood(raw_);
                        if (!nraw_.Contains(v))
                            newValue = int.MaxValue;

                        int min = Math.Min(savedValue, newValue);
                        newTable[rw, outside] = min;

                        //--------

                        nrw_ = graph.Neighborhood(outside + v) * (left - v);
                        ra_ = LRa_.GetRepresentative(nrw_);

                        nra = graph.Neighborhood(inside + v) * right;
                        rw = LRw.GetRepresentative(nra);

                        savedValue = newTable[rw, outside];
                        newValue = table[inside, ra_];
                        newValue = newValue == int.MaxValue ? newValue : newValue + 1;
                        min = Math.Min(savedValue, newValue);
                        newTable[rw,  outside] = min;
                    }
                }

                table = newTable;
            }

            return table[new BitSet(0, graph.Size), new BitSet(0, graph.Size)];
        }
コード例 #7
0
        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;
            }
        }
コード例 #8
0
ファイル: CountIS.cs プロジェクト: FrankvH/BooleanWidth
        public static void Compute(LinearDecomposition decomposition)
        {
            Graph graph = decomposition.Graph;
            List<int> sequence = decomposition.Sequence;
            int n = graph.Size;

            BitSet right = graph.Vertices;
            BitSet left = new BitSet(0, n);

            LookupTable table = new LookupTable(n);
            LinearRepresentativeTable cuts = new LinearRepresentativeTable(graph, sequence);

            table[new BitSet(0, n), 0] = 1;
            table[new BitSet(0, n), 1] = 0;

            for (int i = 0; i < sequence.Count; i++)
            {
                int v = sequence[i];

                left.Add(v);
                right.Remove(v);

                LinearRepresentativeList LRw = cuts[left];

                LinearRepresentativeList LRa = cuts[left - v];

                LookupTable newTable = new LookupTable(n);

                foreach (BitSet ra in LRa)
                {
                    BitSet nra = graph.Neighborhood(ra) * right;
                    BitSet rw = LRw.GetRepresentative(nra);

                    int maxValue = int.MinValue;
                    int limit = (left - v).Count;
                    for (int k = 0; k <= limit; k++)
                        if (table[ra, k] > 0)
                            maxValue = Math.Max(maxValue, k);

                    for (int j = 0; j <= maxValue; j++)
                    {
                        newTable[rw, j] = newTable[rw, j] + table[ra, j];
                    }

                    //------------

                    // ra + {v} is not a valid independent set
                    if (LRa.GetNeighborhood(ra).Contains(v))
                        continue;

                    //------------

                    // add {v} to the independent set
                    BitSet nrav = graph.Neighborhood(ra + v) * right;
                    BitSet rwv = LRw.GetRepresentative(nrav);

                    for (int j = 0; j <= maxValue; j++)
                    {
                        newTable[rwv, j + 1] = newTable[rwv, j + 1] + table[ra, j];
                    }
                }

                table = newTable;
            }

            return;
        }
コード例 #9
0
        // 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;
        }
コード例 #10
0
        public static LinearDecomposition Compute(Graph graph, ScoreFunction scoreFunction)
        {
            // We solve finding an ordering for each connected component of the graph seperately
            List<BitSet> connectedComponents = DepthFirstSearch.ConnectedComponents(graph);

            // The final sequence that we will return
            List<int> sequence = new List<int>();

            // Shorthand notation
            int n = graph.Size;

            foreach (BitSet connectedComponent in connectedComponents)
            {
                // Set of unprocessed vertices
                BitSet right = connectedComponent.Copy();

                // Set of processed vertices
                BitSet left = new BitSet(0, n);

                // The initial is selected by a certain strategy (in this case a double BFS)
                int init = Heuristics.BFS(graph, Heuristics.BFS(graph, connectedComponent.Last()));

                // Place init in the sequence
                sequence.Add(init);
                left.Add(init);
                right.Remove(init);

                // Continue while not all unprocessed vertices are moved
                while (!right.IsEmpty)
                {
                    int chosen = Heuristics.TrivialCases(graph, left, right);

                    // If chosen has not been set it means that no trivial case was found
                    // Depending on the criteria for the next vertex we call a different algorithm
                    if (chosen == -1)
                    {
                        switch (scoreFunction)
                        {
                            case ScoreFunction.LeastUncommonNeighbor:
                                chosen = LeastUncommonNeighbor(graph, left, right);
                                break;
                            case ScoreFunction.RelativeNeighborhood:
                                chosen = RelativeNeighborhood(graph, left, right);
                                break;
                            case ScoreFunction.LeastCutValue:
                                chosen = LeastCutValue(graph, left, right);
                                break;
                        }
                    }

                    // This should never happen; a selection criteria should always return some vertex
                    if (chosen == -1)
                        throw new Exception("No vertex is chosen for next step in the heuristic");

                    // Add/remove the next vertex in the appropiate sets
                    sequence.Add(chosen);
                    left.Add(chosen);
                    right.Remove(chosen);

                }
            }
            return new LinearDecomposition(graph, sequence);
        }
コード例 #11
0
        public static int Compute(LinearDecomposition decomposition)
        {
            Graph graph = decomposition.Graph;
            List<int> sequence = decomposition.Sequence;

            // Left is the set of vertices that have been processed so far.
            BitSet left = new BitSet(0, graph.Size);

            // Right is the set of vertices that we have yet to process, initially set to all vertices in the graph.
            BitSet right = graph.Vertices;

            // The leftneighborset contains ISN elements, that save the size of each independent set in Left, and the corresponding neighborhood in Right that belongs to this IS.
            LookupTable table = new LookupTable();

            // Insert the initial neighborhood and IS of size 0 and an empty neighborhood.
            table.Update(new ISN(new BitSet(0, graph.Size), 0));

            // maxIS saves the largest independent set that we have encountered so far.
            int maxIS = 0;

            // Loop over all vertices in the sequence; we have to process all of them.
            for (int i = 0; i < sequence.Count; i++)
            {
                // Take the next vertex in the sequence.
                int v = sequence[i];

                //Save all updated element in a new neighborset, so that we do not disturb any looping over elements.
                LookupTable newTable = new LookupTable();

                foreach (ISN iset in table)
                {
                    // If a neighborhood Right contains the currently selected element, then we have to remove it from the neighborhood.
                    // The corresponding IS in Left is still valid, but it simply belongs to a smaller neighborhood in Right (hence the removal of v).
                    if (iset.Elements.Contains(v))
                    {
                        iset.Elements.Remove(v);
                        newTable.Update(iset);
                    }
                    // If the neighborhood does not contain v, then there are two cases that have to be handled.
                    else
                    {
                        // Case a: If v is not an element of the largest IS, then the previous IS is still valid.
                        // We have no risk of v being contained in the neighborhood of Right, because if that would be the case we would not be in the else-part of the if-statement.
                        // Thus, we simply add an unmodified copy of j to the new list of neighborhoodsets.
                        newTable.Update(iset);

                        // Case b: If v is an element of the largest IS, then we should include a new entry for this newly created IS.
                        // The size of this IS will increase by one (adding v will cause this).
                        // The neighborhood of this IS is the old neighborhood, plus any vertices in Right that are in the neighborhood of v. Vertex v causes the addition of these vertices.
                        // The largest saved IS might change because of this addition of a new erlement.
                        ISN newIset = new ISN(iset.Elements.Copy(), iset.Size);
                        newIset.Size++;
                        newIset.Elements = newIset.Elements + (graph.OpenNeighborhood(v) * right);
                        maxIS = Math.Max(maxIS, newIset.Size);
                        newTable.Update(newIset);
                    }
                }

                // Safely update all sets that we are working with
                left.Add(v);
                right.Remove(v);
                table = newTable;

            }
            // The largest IS that we have encountered is the one we will return
            return maxIS;
        }
コード例 #12
0
ファイル: CountDS.cs プロジェクト: FrankvH/BooleanWidth
        public static void Compute(LinearDecomposition decomposition)
        {
            Graph graph = decomposition.Graph;
            List<int> sequence = decomposition.Sequence;
            int n = graph.Size;

            BitSet right = graph.Vertices;
            BitSet left = new BitSet(0, n);

            LookupTable table = new LookupTable(n);

            LinearRepresentativeTable cuts = new LinearRepresentativeTable(graph, sequence);

            int l = sequence[0];
            BitSet leaf = new BitSet(0, n) { l };
            BitSet nleaf = new BitSet(0, n) { graph.OpenNeighborhood(l).First() };

            table[leaf, new BitSet(0, n), 1] = 1;
            table[leaf, nleaf, 1] = 1;
            table[new BitSet(0, n), nleaf, 0] = 1;

            left.Add(l);
            right.Remove(l);

            for (int i = 1; i < sequence.Count; i++)
            {
                int v = sequence[i];

                left.Add(v);
                right.Remove(v);

                LinearRepresentativeList LRw = cuts[left];
                LinearRepresentativeList LRw_ = cuts[right];

                LinearRepresentativeList LRa = cuts[left - v];
                LinearRepresentativeList LRa_ = cuts[right + v];

                LookupTable newTable = new LookupTable(n);

                foreach (BitSet outside in LRw_)
                {
                    foreach (BitSet inside in LRa)
                    {
                        BitSet nrw_ = graph.Neighborhood(outside) * (left - v);
                        BitSet ra_ = LRa_.GetRepresentative(nrw_);

                        BitSet nra = graph.Neighborhood(inside) * right;
                        BitSet rw = LRw.GetRepresentative(nra);

                        BitSet ra = inside;
                        BitSet rw_ = outside;

                        BitSet raw_ = inside + outside;
                        BitSet nraw_ = graph.Neighborhood(raw_);
                        if (nraw_.Contains(v))  // this means rb_ exists ==> multiplier is equal to 1
                        {
                            for (int ka = 0; ka < n; ka++)
                            {
                                newTable[rw, rw_, ka] = newTable[rw, rw_, ka] + table[ra, ra_, ka];
                            }
                        }

                        //--------

                        nrw_ = graph.Neighborhood(outside + v) * (left - v);
                        ra_ = LRa_.GetRepresentative(nrw_);

                        nra = graph.Neighborhood(inside + v) * right;
                        rw = LRw.GetRepresentative(nra);

                        for (int ka = 0; ka < n; ka++)
                        {
                            newTable[rw, rw_, ka + 1] = newTable[rw, rw_, ka + 1] + table[ra, ra_, ka];
                        }
                    }
                }

                table = newTable;
            }

            return;
        }
コード例 #13
0
ファイル: IUNHeuristic.cs プロジェクト: FrankvH/BooleanWidth
        private static List<int> ComputeSequence(Graph graph, BitSet connectedComponent, CandidateStrategy candidateStrategy, int init, out int value)
        {
            int n = graph.Size;
            List<int> sequence = new List<int>() { init };
            BitSet left = new BitSet(0, n) { init };
            BitSet right = connectedComponent - init;

            // Initially we store the empty set and the set with init as the representative, ie N(init) * right
            Set<BitSet> UN_left = new Set<BitSet>() { new BitSet(0, n), graph.OpenNeighborhood(init) * right };
            value = int.MinValue;
            while (!right.IsEmpty)
            {
                Set<BitSet> UN_chosen = new Set<BitSet>();
                int chosen = Heuristics.TrivialCases(graph, left, right);

                if (chosen != -1)
                {
                    UN_chosen = IncrementUN(graph, left, UN_left, chosen);
                }
                // If chosen has not been set it means that no trivial case was found
                // Depending on the criteria for the next vertex we call a different algorithm
                else
                {
                    BitSet candidates = Heuristics.Candidates(graph, left, right, candidateStrategy);

                    int min = int.MaxValue;

                    foreach (int v in candidates)
                    {
                        Set<BitSet> UN_v = IncrementUN(graph, left, UN_left, v);
                        if (UN_v.Count < min)
                        {
                            chosen = v;
                            UN_chosen = UN_v;
                            min = UN_v.Count;
                        }
                    }
                }

                // This should never happen
                if (chosen == -1)
                    throw new Exception("No vertex is chosen for next step in the heuristic");

                // Add/remove the next vertex in the appropiate sets
                sequence.Add(chosen);
                left.Add(chosen);
                right.Remove(chosen);
                UN_left = UN_chosen;
                value = Math.Max(UN_chosen.Count, value);
            }

            return sequence;
        }