예제 #1
0
        /*************************/
        // Selecting initial vertices
        /*************************/
        // Returns a vertex on the last level of a Breadth-first search (BFS)
        public static int BFS(Graph graph, int init)
        {
            // BFS working queue
            Queue<int> queue = new Queue<int>();
            // Vertices that have already been visited
            Set<int> visited = new Set<int>();

            // Initial vertex is given as input
            visited.Add(init);
            queue.Enqueue(init);
            int current = init;

            // While there is still a vertex in the queue...
            while (queue.Count > 0)
            {
                //... select the first vertex and process it
                current = queue.Dequeue();
                foreach (int w in graph.OpenNeighborhood(current))
                {
                    // Enqueue all neighbors that have not been processed yet
                    if (!visited.Contains(w))
                    {
                        visited.Add(w);
                        queue.Enqueue(w);
                    }
                }
            }
            // This is the last vertex that has been processed, thus a vertex that is on the last level of the BFS search
            return current;
        }
예제 #2
0
        // Constructor for creating a new representative table. We directly fill the table depending on the given sequence.
        public RepresentativeTable(Graph graph, Tree tree)
        {
            // Initialize the table
            Table = new Dictionary<BitSet, RepresentativeList>();

            Queue<BitSet> queue = new Queue<BitSet>();
            queue.Enqueue(tree.Root);
            Table[new BitSet(0, graph.Size)] = new RepresentativeList();

            int i = 0;

            while (queue.Count != 0)
            {
                BitSet node = queue.Dequeue();

                FillTable(graph, node);
                FillTable(graph, graph.Vertices - node);

                if (tree.LeftChild.ContainsKey(node))
                {
                    queue.Enqueue(tree.LeftChild[node]);
                }
                if (tree.RightChild.ContainsKey(node))
                {
                    queue.Enqueue(tree.RightChild[node]);
                }
            }
        }
예제 #3
0
        // Uses depth-first search to check if the graph induced by the subgraph given as a parameter is connected
        // In other words, we retreive all edges from the original graph and check the subgraph for connectedness
        public static bool Connected(Graph graph, BitSet subgraph)
        {
            // Vertices that are visited
            Set<int> visited = new Set<int>();

            // Stack of vertices yet to visit
            Stack<int> stack = new Stack<int>();

            // Initial vertex
            int s = subgraph.First();
            stack.Push(s);

            // Continue while there are vertices on the stack
            while (stack.Count > 0)
            {
                int v = stack.Pop();

                // If we have not encountered this vertex before, 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
                if (!visited.Contains(v))
                {
                    visited.Add(v);

                    foreach (int w in graph.OpenNeighborhood(v))
                        if (subgraph.Contains(w))
                            stack.Push(w);
                }
            }

            // If we visited an equal number of vertices as there are vertices in the subgraph then the subgraph is connected
            return visited.Count == subgraph.Count;
        }
예제 #4
0
        // 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;
        }
예제 #5
0
        /*************************/
        // Computing Exact Decompositions
        /*************************/
        public static Decomposition Compute(Graph graph)
        {
            Initialize(graph.Size);

            // Construct the table with the correct width values
            ConstructTree(graph, graph.Vertices);

            // Retrieve a sequence that will result in our bound not being exceeded
            Tree tree = RetrieveTree(graph);

            return new Decomposition(graph, tree);
        }
예제 #6
0
        /*************************/
        // Computing Exact Linear Decompositions
        /*************************/
        public static LinearDecomposition ExactlinearDecomposition(Graph graph)
        {
            Initialize(graph.Size);

            // Construct the table with the correct width values
            ConstructSequence(graph, graph.Vertices);

            // Retrieve a sequence that will result in our bound not being exceeded
            List<int> sequence = RetrieveSequence(graph, graph.Vertices);

            return new LinearDecomposition(graph, sequence);
        }
예제 #7
0
        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;
        }
예제 #8
0
        // 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]);
        }
        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;
            }
        }
예제 #10
0
        // 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);
            }
        }
예제 #11
0
        // 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;
        }
예제 #12
0
        // 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);
        }
예제 #13
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;
        }
예제 #14
0
        // 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;
        }
예제 #15
0
        public static LinearDecomposition Compute(Graph graph, CandidateStrategy candidateStrategy, InitialVertexStrategy initialVertexStrategy)
        {
            List<BitSet> connectedComponents = DepthFirstSearch.ConnectedComponents(graph);
            List<int> sequence = new List<int>();

            int tempValue;
            foreach (BitSet connectedComponent in connectedComponents)
            {
                switch (initialVertexStrategy)
                {
                    case InitialVertexStrategy.All:
                        {
                            List<int> minList = null;
                            int minValue = int.MaxValue;
                            foreach (int vertex in connectedComponent)
                            {
                                List<int> temp = ComputeSequence(graph, connectedComponent, candidateStrategy, vertex, out tempValue);
                                if (tempValue < minValue)
                                {
                                    minValue = tempValue;
                                    minList = temp;
                                }
                            }
                            sequence.AddRange(minList);
                        }
                        break;
                    case InitialVertexStrategy.BFS:
                        {
                            int init = Heuristics.BFS(graph, connectedComponent.Last());
                            sequence.AddRange(ComputeSequence(graph, connectedComponent, candidateStrategy, init, out tempValue));
                        }
                        break;
                    case InitialVertexStrategy.DoubleBFS:
                        {
                            int init = Heuristics.BFS(graph, Heuristics.BFS(graph, connectedComponent.Last()));
                            sequence.AddRange(ComputeSequence(graph, connectedComponent, candidateStrategy, init, out tempValue));
                        }
                        break;
                }
            }
            return new LinearDecomposition(graph, sequence);
        }
        // Constructor for creating a new representative table. We directly fill the table depending on the given sequence.
        public LinearRepresentativeTable(Graph graph, List<int> sequence)
        {
            // Initialize the table
            Table = new Dictionary<BitSet, LinearRepresentativeList>();

            int n = graph.Size;

            // Save these initial representatives for the cut(empty, V(G))
            LinearRepresentativeList reps = new LinearRepresentativeList();
            reps.Update(new BitSet(0, n), new BitSet(0, n));
            Table[new BitSet(0, n)] = reps;
            Table[graph.Vertices] = reps;

            FillTable(graph, sequence);

            List<int> reverseSequence = new List<int>();
            for (int i = sequence.Count - 1; i >= 0; i--)
                reverseSequence.Add(sequence[i]);

            FillTable(graph, reverseSequence);
        }
예제 #17
0
        // Constructs the actual width values
        // The idea is the following: If we want to know the optimal width for a certain cut A, thus Width[A], then we can obtain this by
        // either taking the max(Cuts[A], the minimum over all widths of Width[A - a]), which is our recurrence relation.
        private static void ConstructSequence(Graph graph, BitSet A)
        {
            // min saves the minimum size of all neighborhoods of the cut [A - a], where a can be any vertex in A
            long min = long.MaxValue;

            // v will be the optimal choice to leave out in the previous iteration in order to obtain A's full neighborhood
            int v = -1;

            foreach (int a in A)
            {
                BitSet previous = A - a;

                // If we have not constructed the previous step yet, then go in recursion and do so
                if (!Neighborhoods.ContainsKey(previous))
                    ConstructSequence(graph, previous);

                // Save the minimum value
                if (Width[previous] < min)
                {
                    min = Width[previous];
                    v = a;
                }
            }

            // Obtain the neighborhood of v
            BitSet nv = graph.OpenNeighborhood(v) * (graph.Vertices - A);

            // We save the full set of neighborhood vertices at cut A. It does not matter that v was chosen arbitrarely; we always end up in the same collection of neighboring vertices for the set A
            Set<BitSet> un = new Set<BitSet>();
            foreach (BitSet _base in Neighborhoods[A - v])
            {
                un.Add(_base - v);          // previous neighbor without v is a possible new neighborhood
                un.Add((_base - v) + nv);   // previous neighbor without v, unioned with the neighborhood of v is a possible new neighborhood
            }

            // Save all entries
            Neighborhoods[A] = un;              // List of all neighbors at cut A
            Cuts[A] = Neighborhoods[A].Count;   // Dimension at this cut
            Width[A] = Math.Max(min, Cuts[A]);  // Actual possible width to get to this cut
        }
예제 #18
0
        // 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;
        }
예제 #19
0
        /*************************/
        // Trivial cases
        /*************************/
        public static int TrivialCases(Graph graph, BitSet left, BitSet right)
        {
            int chosen = -1;

            // Check if any vertex in right belongs to one of the trivial cases, if yes then we can add this vertex directly to the sequence
            foreach (int v in right)
            {
                // Trivial case 1. If the neighbors of a vertex v in right are all contained in left, then select v
                // What this means is that v has an empty neighborhood, thus it will not add anything to the boolean-dimension
                if ((graph.OpenNeighborhood(v) - left).IsEmpty)
                {
                    chosen = v;

                    break;
                }

                bool stop = false;
                // 2. If there are two vertices, v in right and u in left, such that N(v) * right == (N(u)\v) * right,
                // then v is selected as our next vertex
                // What this means is that all neighbors of v are already 'represented' by u, thus making the choice for v will not add anything to the dimension
                foreach (int u in left)
                {
                    BitSet nv = graph.OpenNeighborhood(v) * right;  // N(v) * right
                    BitSet nu = (graph.OpenNeighborhood(u) - v) * right;    // (N(u)\v) * right
                    if (nv.Equals(nu))
                    {
                        chosen = v;
                        stop = true;
                        break;
                    }
                }

                if (stop) break;
            }

            return chosen;
        }
예제 #20
0
 /*************************/
 // 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;
 }
예제 #21
0
        // Retreives the actual ordering of a certain ordering that will not validate our bound
        private static List<int> RetrieveSequence(Graph graph, BitSet A)
        {
            List<int> sequence = new List<int>();

            // We know that the value saved at Width[graph.Vertices] will be the best value that we can get
            // Furthermore, we know that there is a possibility to remove a vertex and get a smaller or equal Width value, in other words Width[A - a] <= Width[A]
            // This way we navigate through the table and find a sequence that never will exceed the bound that is set, and we know for sure
            // that such a path exists.
            foreach (int a in A)
            {
                BitSet previous = A - a;
                if (Width[previous] <= Width[graph.Vertices])
                {
                    sequence.Add(a);
                    sequence.AddRange(RetrieveSequence(graph, previous));
                    break;
                }
            }

            return sequence;
        }
예제 #22
0
 public static bool Connected(Graph graph)
 {
     return Connected(graph, graph.Vertices);
 }
예제 #23
0
        // Implementation of Algorithm 13 of the PhD thesis by Sadia Sharmin
        // The LeastCutValue selection method picks the next vertex based on a greedy choice, namely what is the vertex that will have the least
        // influence on the boolean dimension at this point.
        // While this generally gives great results, the runtime is very high because we construct multiple bipartite graphs during every iteration.
        private static int LeastCutValue(Graph graph, BitSet left, BitSet right)
        {
            // Minimum boolean dimension that we can have for our next cut
            long minBoolDim = long.MaxValue;

            // Vertex that we will choose
            int chosen = -1;

            // Foreach candidate vertex we construct a bipartite graph and count the number of minimal independent sets in this bipartite graph
             //This number is equal to the boolean-dimension at this cut
            foreach (int v in right)
            {
                // Construct the bipartite graph
                BipartiteGraph bg = new BipartiteGraph(graph, left + v, right - v);

                // Count the number of MIS in the bipartite graph
                long boolDim = CC_MIS.Compute(bg);

                // Possibly update the minimum value found so far
                if (boolDim < minBoolDim)
                {
                    chosen = v;
                    minBoolDim = boolDim;
                }
            }

            return chosen;
        }
예제 #24
0
 /*************************/
 // Constructor
 /*************************/
 public Decomposition(Graph graph, Tree tree)
 {
     Tree = tree;
     Graph = graph;
 }
예제 #25
0
 public static List<BitSet> ConnectedComponents(Graph graph)
 {
     return ConnectedComponents(graph, graph.Vertices);
 }
예제 #26
0
 // Basic constructor
 public LinearDecomposition(Graph graph, List<int> sequence)
 {
     Sequence = sequence;
     Graph = graph;
 }
예제 #27
0
 // Initial call
 public static long Compute(Graph graph)
 {
     return Compute(graph, new BitSet(0, graph.Size), graph.Vertices, new BitSet(0, graph.Size));
 }
예제 #28
0
        // Constructs the actual width values
        private static void ConstructTree(Graph graph, BitSet A)
        {
            long min = A.Count == 1 ? 0 : long.MaxValue;
            int n = graph.Size;
            int v = -1;     // v is the vertex that if we remove it from A, we have the smallest number of neighbors
            BitSet optimal = new BitSet(0, n);

            Set<BitSet> subsets = new Set<BitSet>(new BitSet(0, n));
            foreach (int a in A)
            {
                Set<BitSet> newSubsets = new Set<BitSet>();
                foreach (BitSet j in subsets)
                {
                    BitSet subset = j + a;
                    BitSet inverse = A - subset;

                    if (subset.Equals(A)) continue; // only consider strict subsets

                    if (!Width.ContainsKey(subset))
                        ConstructTree(graph, subset);

                    if (!Width.ContainsKey(inverse))
                        ConstructTree(graph, inverse);

                    newSubsets.Add(subset); // add this for the next iteration

                    long max = Math.Max(Width[subset], Width[inverse]); // either S or A\S will be the bottleneck

                    if (max < min)
                    {
                        min = max;
                        optimal = subset; // it doesn't matter if we take j + a or A - (j + a), since when retrieving the tree we split them anyway

                        if (inverse.Count == 1)
                            v = inverse.First();
                    }
                }

                subsets.AddRange(newSubsets);
            }

            v = v == -1 ? A.First() : v;
            BitSet nv = graph.OpenNeighborhood(v) * (graph.Vertices - (A - v));
            Set<BitSet> un = new Set<BitSet>();
            foreach (BitSet _base in Neighborhoods[A - v])
            {
                un.Add(_base - v);          // previous neighbor without v is a possible new neighborhood
                un.Add((_base - v) + nv);   // previous neighbor without v, unioned with the neighborhood of v is a possible new neighborhood
            }
            Neighborhoods[A] = un;
            Cuts[A] = Neighborhoods[A].Count;

            Width[A] = Math.Max(min, Cuts[A]);  // Actual possible width to get to this cut
            OptimalChild[A] = optimal;
        }
예제 #29
0
        // Parses a file of DGF format, from which we can build a graph
        public static Graph ParseGraph(string filename)
        {
            StreamReader sr = new StreamReader (filename);

            string line;
            int nVertices = 0;

            // First we parse the number of vertices
            while ((line = sr.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 = sr.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);
                }
            }

            sr.Close ();
            return graph;
        }
예제 #30
0
        // Retreives the actual ordering of a certain ordering that will not validate our bound
        private static Tree RetrieveTree(Graph graph)
        {
            Tree tree = new Tree();

            Queue<BitSet> queue = new Queue<BitSet>();
            queue.Enqueue(graph.Vertices);

            while (queue.Count != 0)
            {
                BitSet A = queue.Dequeue();
                tree.Insert(A);

                if (OptimalChild[A].IsEmpty) continue;

                queue.Enqueue(OptimalChild[A]);
                queue.Enqueue(A - OptimalChild[A]);
            }

            return tree;
        }