private void SetChainPositions(VertexListMatrix chains, VertexIntDictionary chain_number, VertexIntDictionary pos_in_chain) // Record chain number and position in chain of each vertex in chains { if (chain_number == null) { throw new ArgumentNullException("chain_number"); } if (pos_in_chain == null) { throw new ArgumentNullException("pos_in_chain"); } for (int i = 0; i < chains.RowCount; i++) { for (int j = 0; j < chains[i].Count; j++) { IVertex v = (IVertex)chains[i][j]; if (!chain_number.ContainsKey(v)) { chain_number.Add(v, i); } if (!pos_in_chain.ContainsKey(v)) { pos_in_chain.Add(v, j); } } } }
/// <summary> /// Compute the transitive closure and store it in the supplied graph 'tc' /// </summary> /// <param name="tc"> /// Mutable Graph instance to store the transitive closure /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="tc"/> is a <null/>. /// </exception> public void Create(IMutableVertexAndEdgeListGraph tc) { if (tc == null) { throw new ArgumentNullException("tc"); } CondensationGraphAlgorithm cgalgo = new CondensationGraphAlgorithm(VisitedGraph); cgalgo.Create(cg); ArrayList topo_order = new ArrayList(cg.VerticesCount); TopologicalSortAlgorithm topo = new TopologicalSortAlgorithm(cg, topo_order); topo.Compute(); VertexIntDictionary in_a_chain = new VertexIntDictionary(); VertexIntDictionary topo_number = new VertexIntDictionary(); for (int order = 0; order < topo_order.Count; order++) { IVertex v = (IVertex)topo_order[order]; topo_number.Add(v, order); if (!in_a_chain.Contains(v)) // Initially no vertex is present in a chain { in_a_chain.Add(v, 0); } } VertexListMatrix chains = new VertexListMatrix(); int position = -1; foreach (IVertex v in topo_order) { if (in_a_chain[v] == 0) { // Start a new chain position = chains.AddRow(); IVertex next = v; for (;;) { chains[position].Add(next); in_a_chain[next] = 1; // Get adjacent vertices ordered by topological number // Extend the chain by choosing the adj vertex with lowest topo# ArrayList adj = TopoSortAdjVertices(next, cg, topo_number); if ((next = FirstNotInChain(adj, in_a_chain)) == null) { break; } } } } VertexIntDictionary chain_number = new VertexIntDictionary(); VertexIntDictionary pos_in_chain = new VertexIntDictionary(); // Record chain positions of vertices SetChainPositions(chains, chain_number, pos_in_chain); VertexListMatrix successors = new VertexListMatrix(); successors.CreateObjectMatrix(cg.VerticesCount, chains.RowCount, int.MaxValue); if (topo_order.Count > 0) { for (int rtopo = topo_order.Count - 1; rtopo > -1; rtopo--) { IVertex u = (IVertex)topo_order[rtopo]; foreach (IVertex v in TopoSortAdjVertices(u, cg, topo_number)) { if (topo_number[v] < (int)successors[u.ID][chain_number[v]]) { // {succ(u)} = {succ(u)} U {succ(v)} LeftUnion(successors[u.ID], successors[v.ID]); // {succ(u)} = {succ(u)} U {v} successors[u.ID][chain_number[v]] = topo_number[v]; } } } } // Create transitive closure of condensation graph // Remove existing edges in CG & rebuild edges for TC from // successor set (to avoid duplicating parallel edges) ArrayList edges = new ArrayList(); foreach (IEdge e in cg.Edges) { edges.Add(e); } foreach (IEdge e in edges) { cg.RemoveEdge(e); } foreach (IVertex u in cg.Vertices) { int i = u.ID; for (int j = 0; j < chains.RowCount; j++) { int tnumber = (int)successors[i][j]; if (tnumber < int.MaxValue) { IVertex v = (IVertex)topo_order[tnumber]; for (int k = pos_in_chain[v]; k < chains[j].Count; k++) { cg.AddEdge(u, (IVertex)chains[j][k]); } } } } // Maps a vertex in input graph to it's transitive closure graph graphTransitiveClosures = new VertexVertexDictionary(); // Add vertices to transitive closure graph foreach (IVertex v in visitedGraph.Vertices) { if (!graphTransitiveClosures.Contains(v)) { IVertex vTransform = tc.AddVertex(); OnInitTransitiveClosureVertex( new TransitiveClosureVertexEventArgs( v, vTransform) ); // Fire the TC Vertex Event graphTransitiveClosures.Add(v, vTransform); } } //Add edges connecting vertices within SCC & adjacent // SCC (strongly connected component) IVertexCollection scc_vertices = null; foreach (IVertex s_tccg in cg.Vertices) { scc_vertices = (IVertexCollection)cgalgo.SCCVerticesMap[s_tccg.ID]; if (scc_vertices.Count > 1) { foreach (IVertex u in scc_vertices) { foreach (IVertex v in scc_vertices) { OnExamineEdge(tc.AddEdge(graphTransitiveClosures[u], graphTransitiveClosures[v])); } } } foreach (IEdge adj_edge in cg.OutEdges(s_tccg)) { IVertex t_tccg = adj_edge.Target; foreach (IVertex s in (IVertexCollection)cgalgo.SCCVerticesMap[s_tccg.ID]) { foreach (IVertex t in (IVertexCollection)cgalgo.SCCVerticesMap[t_tccg.ID]) { OnExamineEdge(tc.AddEdge(graphTransitiveClosures[s], graphTransitiveClosures[t])); } } } } }