/// <summary>
        /// replaces the old adjacency list with a new one where all removed vertices no longer occupy a spot in the list. A mapping that maps the new vertices back to the old ones is returned.
        /// </summary>
        /// <param name="reconstructionIndexationMapping"></param>
        public void Reduce(out ReindexationMapping reconstructionIndexationMapping)
        {
            if (!isReduced)
            {
                reconstructionIndexationMapping = null;
                return;
            }

            BuildReindexationMappings(out reconstructionIndexationMapping, out Dictionary <int, int> reductionMapping);

            vertexCount = 0;
            edgeCount   = 0;

            // use that mapping to reduce the adjacency list for this graph
            List <int>[] reducedAdjacencyList = new List <int> [reductionMapping.Count];
            int          vertex = -1;

            while ((vertex = notRemovedVertices.NextElement(vertex)) != -1)
            {
                vertexCount++;

                List <int> currentVertexAdjacencies = new List <int>(adjacencyList[vertex].Count);
                for (int j = 0; j < adjacencyList[vertex].Count; j++)
                {
                    int neighbor = adjacencyList[vertex][j];
                    currentVertexAdjacencies.Add(reductionMapping[neighbor]);
                }
                reducedAdjacencyList[reductionMapping[vertex]] = currentVertexAdjacencies;
                edgeCount += currentVertexAdjacencies.Count;
            }
            edgeCount            /= 2;
            notRemovedVertexCount = vertexCount;

            adjacencyList      = reducedAdjacencyList;
            notRemovedVertices = BitSet.All(vertexCount);
            openNeighborhood   = new BitSet[vertexCount];
            closedNeighborhood = new BitSet[vertexCount];
            for (int i = 0; i < vertexCount; i++)
            {
                openNeighborhood[i]      = new BitSet(vertexCount, adjacencyList[i]);
                closedNeighborhood[i]    = new BitSet(openNeighborhood[i]);
                closedNeighborhood[i][i] = true;
            }

            isReduced = false;

            if (verbose)
            {
                Console.WriteLine("reduced graph {0} to {1} vertices and {2} edges", graphID, reducedAdjacencyList.Length, edgeCount);
            }
        }
        /// <summary>
        /// Constructs both a forward and a backward mapping between reduced vertex indices and original vertex indices.
        /// </summary>
        /// <param name="reindexationMapping">the mapping from reduced vertex indices back to original vertex indices</param>
        /// <param name="reductionMapping">the mapping from original vertex indices to reduced vertex indices</param>
        private void BuildReindexationMappings(out ReindexationMapping reindexationMapping, out Dictionary <int, int> reductionMapping)
        {
            reindexationMapping = new ReindexationMapping(vertexCount);

            reductionMapping = new Dictionary <int, int>();
            int counter = 0;
            int vertex  = -1;

            while ((vertex = notRemovedVertices.NextElement(vertex)) != -1)
            {
                reductionMapping.Add(vertex, counter);
                reindexationMapping.Add(vertex);
                counter++;
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// reindexes the vertices of this ptd that is a ptd of a reduced graph, so that they correctly represent the same vertices in the non-reduced graph.
        /// </summary>
        /// <param name="reindexationMapping">the mapping from the vertex indices in the current ptd to their original vertex indices within the original graph.</param>
        public void Reindex(ReindexationMapping reindexationMapping)
        {
            // initialize a stack of nodes
            Stack <PTD> nodeStack = new Stack <PTD>();

            nodeStack.Push(this);

            // re-index all bags with the vertices they had before reduction
            while (nodeStack.Count > 0)
            {
                PTD    currentNode = nodeStack.Pop();
                BitSet reducedBag  = currentNode.Bag;

                BitSet reconstructedBag = reindexationMapping.Reindex(reducedBag);
                currentNode.SetBag(reconstructedBag);

                // push children onto stack
                for (int i = 0; i < currentNode.children.Count; i++)
                {
                    nodeStack.Push(currentNode.children[i]);
                }
            }
        }
        /// <summary>
        /// separates the graph at a given safe separator into subgraphs.
        /// If a tree decomposition for one subgraph has already been calculated, the index of that subgraph is also given out
        /// </summary>
        /// <param name="separator">the safe separator</param>
        /// <param name="reconstructionIndexationMappings">the corresponding mapping for reindexing the vertices in the subgraphs back to their old indices within this graph</param>
        /// <param name="alreadyCalculatedComponent">Optionally, a component whose subgraph has an already calculated PTD.
        ///                                         (This happens when a safe separator is found during the "HasTreewidth" calculation.)</param>
        /// <param name="alreadyCalculatedComponentIndex">-1, if no alreadyCalculatedComponent is passed, else the index in the list of subgraphs of the subgraph corresponding to that component</param>
        /// <returns>a list of the subgraphs</returns>
        public List <Graph> Separate(BitSet separator, out List <ReindexationMapping> reconstructionIndexationMappings, out int alreadyCalculatedComponentIndex, BitSet alreadyCalculatedComponent = null)
        {
            alreadyCalculatedComponentIndex = -1;
            List <Graph> subGraphs         = new List <Graph>();
            List <int>   separatorVertices = separator.Elements();

            reconstructionIndexationMappings = new List <ReindexationMapping>();

            // for each component
            foreach ((BitSet component, BitSet _) in ComponentsAndNeighbors(separator))
            {
                if (alreadyCalculatedComponent != null && component.Equals(alreadyCalculatedComponent))
                {
                    alreadyCalculatedComponentIndex = subGraphs.Count;
                }
                List <int> vertices = component.Elements();
                component.UnionWith(separator);

                // map vertices from this graph to the new subgraph and vice versa
                Dictionary <int, int> reductionMapping = new Dictionary <int, int>(vertexCount + separatorVertices.Count);
                ReindexationMapping   reconstructionIndexationMapping = new ReindexationMapping(vertexCount);
                reconstructionIndexationMappings.Add(reconstructionIndexationMapping);
                for (int i = 0; i < vertices.Count; i++)
                {
                    reductionMapping[vertices[i]] = i;
                    reconstructionIndexationMapping.Add(vertices[i]);
                }

                // don't forget the separator
                for (int i = 0; i < separatorVertices.Count; i++)
                {
                    int u = separatorVertices[i];
                    reductionMapping[u] = vertices.Count + i;
                    reconstructionIndexationMapping.Add(u);
                }

                // create new adjacency list
                List <int>[] subAdjacencyList = new List <int> [vertices.Count + separatorVertices.Count];
                for (int i = 0; i < vertices.Count; i++)
                {
                    int oldVertex = vertices[i];
                    int newVertex = reductionMapping[oldVertex];
                    subAdjacencyList[newVertex] = new List <int>(adjacencyList[oldVertex].Count);
                    foreach (int oldNeighbor in adjacencyList[oldVertex])
                    {
                        int newNeighbor = reductionMapping[oldNeighbor];
                        subAdjacencyList[newVertex].Add(newNeighbor);
                    }
                }

                // also for the separator
                for (int i = 0; i < separatorVertices.Count; i++)
                {
                    int u = separatorVertices[i];
                    subAdjacencyList[vertices.Count + i] = new List <int>();
                    foreach (int oldNeighbor in adjacencyList[u])
                    {
                        if (component[oldNeighbor])
                        {
                            int newNeighbor = reductionMapping[oldNeighbor];
                            subAdjacencyList[vertices.Count + i].Add(newNeighbor);
                        }
                    }
                }

                Graph subGraph = new Graph(subAdjacencyList);
                subGraphs.Add(subGraph);
            }

            // print some stats
            if (verbose)
            {
                Console.WriteLine("splitted graph {0} with {1} vertices and {2} edges into {3} smaller graphs:", graphID, vertexCount, edgeCount, subGraphs.Count);
                foreach (Graph subGraph in subGraphs)
                {
                    Console.WriteLine("        graph {0} with {1} vertices and {2} edges", subGraph.graphID, subGraph.vertexCount, subGraph.edgeCount);
                }
            }

            return(subGraphs);
        }