// 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);
        }
        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 += v;
                right -= 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] = reps;
            }
        }