/// <summary> /// Construct a strong component algorithm /// </summary> /// <param name="g">graph to apply algorithm on</param> /// <exception cref="ArgumentNullException">graph is null</exception> public StrongComponentsAlgorithm(IVertexListGraph g) { if (g==null) throw new ArgumentNullException("g"); this.visitedGraph = g; this.components = new VertexIntDictionary(); this.roots = new VertexVertexDictionary(); this.discoverTimes = new VertexIntDictionary(); this.stack = new Stack(); this.count = 0; this.dfsTime = 0; }
/// <summary> /// /// </summary> /// <param name="g"></param> public StrongComponentsAlgorithm(IVertexListGraph g) { if (g==null) throw new ArgumentNullException("g"); m_VisitedGraph = g; m_Components = new VertexIntDictionary(); m_Roots = new VertexVertexDictionary(); m_DiscoverTimes = new VertexIntDictionary(); m_Stack = new Stack(); m_Count = 0; m_DfsTime = 0; }
/// <summary> /// Builds a new Bellman Ford searcher. /// </summary> /// <param name="g">The graph</param> /// <param name="weights">Edge weights</param> /// <exception cref="ArgumentNullException">Any argument is null</exception> /// <remarks>This algorithm uses the <seealso cref="BreadthFirstSearchAlgorithm"/>.</remarks> public BellmanFordShortestPathAlgorithm( IVertexAndEdgeListGraph g, EdgeDoubleDictionary weights ) { if (weights == null) throw new ArgumentNullException("Weights"); m_VisitedGraph = g; m_Colors = new VertexColorDictionary(); m_Weights = weights; m_Distances = new VertexDoubleDictionary(); m_Predecessors = new VertexVertexDictionary(); }
public DagShortestPathAlgorithm(IVertexListGraph g, EdgeDoubleDictionary weights) { if (g == null) { throw new ArgumentNullException("g"); } if (weights == null) { throw new ArgumentNullException("Weights"); } this.m_VisitedGraph = g; this.m_Colors = new VertexColorDictionary(); this.m_Distances = new VertexDoubleDictionary(); this.m_Predecessors = new VertexVertexDictionary(); this.m_Weights = weights; }
/// <summary> /// Makes a copy of the source graph to the clone graph. /// </summary> /// <param name="source">source graph</param> /// <param name="target">clone graph</param> public void Clone(IVertexAndEdgeListGraph source, IEdgeMutableGraph target) { VertexVertexDictionary vertexMap = new VertexVertexDictionary(); // copy vertices foreach(IVertex v in source.Vertices) { IVertex vc = target.AddVertex(); // clone properties OnCloneVertex(v,vc); // store in table vertexMap[v]=vc; } // copy edges foreach(IEdge e in source.Edges) { IEdge ec = target.AddEdge(vertexMap[e.Source], vertexMap[e.Target]); // cone properties OnCloneEdge(e,ec); } }
/// <summary> /// Checks if the child vertex is a child of the parent vertex /// using the predecessor map. /// </summary> /// <param name="parent"></param> /// <param name="child"></param> /// <param name="predecessors"></param> /// <returns></returns> public static bool IsChild( IVertex parent, IVertex child, VertexVertexDictionary predecessors ) { Object o = predecessors[child]; if (o == null || o==child) // child is the root of the tree return false; else if (o== parent) return true; else return IsChild(parent,(IVertex)o,predecessors); }
public void Init() { parents = new VertexVertexDictionary(); discoverTimes = new VertexIntDictionary(); finishTimes = new VertexIntDictionary(); time = 0; g = new BidirectionalGraph(true); dfs = new UndirectedDepthFirstSearchAlgorithm(g); dfs.StartVertex += new VertexEventHandler(this.StartVertex); dfs.DiscoverVertex += new VertexEventHandler(this.DiscoverVertex); dfs.ExamineEdge += new EdgeEventHandler(this.ExamineEdge); dfs.TreeEdge += new EdgeEventHandler(this.TreeEdge); dfs.BackEdge += new EdgeEventHandler(this.BackEdge); dfs.FinishVertex += new VertexEventHandler(this.FinishVertex); }
/// <summary> /// Builds a new Dijsktra searcher. /// </summary> /// <param name="g">The graph</param> /// <param name="weights">Edge weights</param> /// <exception cref="ArgumentNullException">Any argument is null</exception> /// <remarks>This algorithm uses the <seealso cref="BreadthFirstSearchAlgorithm"/>.</remarks> public DijkstraShortestPathAlgorithm( IVertexListGraph g, EdgeDoubleDictionary weights ) { if (g == null) throw new ArgumentNullException("g"); if (weights == null) throw new ArgumentNullException("Weights"); m_VisitedGraph = g; m_Colors = new VertexColorDictionary(); m_Distances = new VertexDoubleDictionary(); m_Predecessors = new VertexVertexDictionary(); m_Weights = weights; m_VertexQueue = null; }
/// <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])); } } } }
public void Create(IMutableVertexAndEdgeListGraph tc) { if (tc == null) { throw new ArgumentNullException("tc"); } CondensationGraphAlgorithm algorithm = new CondensationGraphAlgorithm(this.VisitedGraph); algorithm.Create(this.cg); ArrayList vertices = new ArrayList(this.cg.get_VerticesCount()); new TopologicalSortAlgorithm(this.cg, vertices).Compute(); VertexIntDictionary dictionary = new VertexIntDictionary(); VertexIntDictionary dictionary2 = new VertexIntDictionary(); for (int i = 0; i < vertices.Count; i++) { IVertex vertex = (IVertex) vertices[i]; dictionary2.Add(vertex, i); if (!dictionary.Contains(vertex)) { dictionary.Add(vertex, 0); } } VertexListMatrix chains = new VertexListMatrix(); int num2 = -1; Label_0112: foreach (IVertex vertex2 in vertices) { if (dictionary.get_Item(vertex2) == 0) { num2 = chains.AddRow(); IVertex vertex3 = vertex2; while (true) { chains[num2].Add(vertex3); dictionary.set_Item(vertex3, 1); ArrayList list2 = this.TopoSortAdjVertices(vertex3, this.cg, dictionary2); vertex3 = this.FirstNotInChain(list2, dictionary); if (vertex3 == null) { goto Label_0112; } } } } VertexIntDictionary dictionary3 = new VertexIntDictionary(); VertexIntDictionary dictionary4 = new VertexIntDictionary(); this.SetChainPositions(chains, dictionary3, dictionary4); VertexListMatrix matrix2 = new VertexListMatrix(); matrix2.CreateObjectMatrix(this.cg.get_VerticesCount(), chains.RowCount, 0x7fffffff); if (vertices.Count > 0) { for (int j = vertices.Count - 1; j > -1; j--) { IVertex v = (IVertex) vertices[j]; foreach (IVertex vertex5 in this.TopoSortAdjVertices(v, this.cg, dictionary2)) { if (dictionary2.get_Item(vertex5) < ((int) matrix2[v.get_ID()][dictionary3.get_Item(vertex5)])) { this.LeftUnion(matrix2[v.get_ID()], matrix2[vertex5.get_ID()]); matrix2[v.get_ID()][dictionary3.get_Item(vertex5)] = dictionary2.get_Item(vertex5); } } } } ArrayList list3 = new ArrayList(); IEdgeEnumerator enumerator = this.cg.get_Edges().GetEnumerator(); while (enumerator.MoveNext()) { IEdge edge = enumerator.get_Current(); list3.Add(edge); } foreach (IEdge edge2 in list3) { this.cg.RemoveEdge(edge2); } IVertexEnumerator enumerator5 = this.cg.get_Vertices().GetEnumerator(); while (enumerator5.MoveNext()) { IVertex vertex6 = enumerator5.get_Current(); int num4 = vertex6.get_ID(); for (int k = 0; k < chains.RowCount; k++) { int num6 = (int) matrix2[num4][k]; if (num6 < 0x7fffffff) { IVertex vertex7 = (IVertex) vertices[num6]; for (int m = dictionary4.get_Item(vertex7); m < chains[k].Count; m++) { this.cg.AddEdge(vertex6, (IVertex) chains[k][m]); } } } } this.graphTransitiveClosures = new VertexVertexDictionary(); IVertexEnumerator enumerator6 = this.visitedGraph.get_Vertices().GetEnumerator(); while (enumerator6.MoveNext()) { IVertex vertex8 = enumerator6.get_Current(); if (!this.graphTransitiveClosures.Contains(vertex8)) { IVertex vertex9 = tc.AddVertex(); this.OnInitTransitiveClosureVertex(new TransitiveClosureVertexEventArgs(vertex8, vertex9)); this.graphTransitiveClosures.Add(vertex8, vertex9); } } IVertexCollection vertexs = null; IVertexEnumerator enumerator7 = this.cg.get_Vertices().GetEnumerator(); while (enumerator7.MoveNext()) { IVertex vertex10 = enumerator7.get_Current(); vertexs = (IVertexCollection) algorithm.SCCVerticesMap[vertex10.get_ID()]; if (vertexs.Count > 1) { IVertexEnumerator enumerator8 = vertexs.GetEnumerator(); while (enumerator8.MoveNext()) { IVertex vertex11 = enumerator8.get_Current(); IVertexEnumerator enumerator9 = vertexs.GetEnumerator(); while (enumerator9.MoveNext()) { IVertex vertex12 = enumerator9.get_Current(); this.OnExamineEdge(tc.AddEdge(this.graphTransitiveClosures.get_Item(vertex11), this.graphTransitiveClosures.get_Item(vertex12))); } } } IEdgeEnumerator enumerator10 = this.cg.OutEdges(vertex10).GetEnumerator(); while (enumerator10.MoveNext()) { IVertex vertex13 = enumerator10.get_Current().get_Target(); IVertexEnumerator enumerator11 = ((IVertexCollection) algorithm.SCCVerticesMap[vertex10.get_ID()]).GetEnumerator(); while (enumerator11.MoveNext()) { IVertex vertex14 = enumerator11.get_Current(); IVertexEnumerator enumerator12 = ((IVertexCollection) algorithm.SCCVerticesMap[vertex13.get_ID()]).GetEnumerator(); while (enumerator12.MoveNext()) { IVertex vertex15 = enumerator12.get_Current(); this.OnExamineEdge(tc.AddEdge(this.graphTransitiveClosures.get_Item(vertex14), this.graphTransitiveClosures.get_Item(vertex15))); } } } } }
public void Init() { parents = new VertexVertexDictionary(); discoverTimes = new VertexIntDictionary(); finishTimes = new VertexIntDictionary(); time = 0; g = new AdjacencyGraph(true); dfs = new DepthFirstSearchAlgorithm(g); dfs.StartVertex += new VertexEventHandler(this.StartVertex); dfs.DiscoverVertex += new VertexEventHandler(this.DiscoverVertex); dfs.ExamineEdge += new EdgeEventHandler(this.ExamineEdge); dfs.TreeEdge += new EdgeEventHandler(this.TreeEdge); dfs.BackEdge += new EdgeEventHandler(this.BackEdge); dfs.ForwardOrCrossEdge += new EdgeEventHandler(this.FowardOrCrossEdge); dfs.FinishVertex += new VertexEventHandler(this.FinishVertex); }
//[SetUp] public void Init() { m_Parents = new VertexVertexDictionary(); m_DiscoverTimes = new VertexIntDictionary(); m_FinishTimes = new VertexIntDictionary(); m_Time = 0; }
public void Init() { m_Parents = new VertexVertexDictionary(); m_Distances = new VertexIntDictionary(); }
//======================================================================= // remove excess flow, the "second phase" // This does a DFS on the reverse flow graph of nodes with excess flow. // If a cycle is found, cancel it. Unfortunately it seems that we can't // easily take advantage of DepthFirstSearchAlgorithm // Return the nodes with excess flow in topological order. // // Unlike the prefl_to_flow() implementation, we use // "color" instead of "distance" for the DFS labels // "parent" instead of nl_prev for the DFS tree // "topo_next" instead of nl_next for the topological ordering private void ConvertPreflowToFlow() { IVertex r, restart, u; IVertex bos = null, tos = null; VertexVertexDictionary parents = new VertexVertexDictionary(); VertexVertexDictionary topoNext = new VertexVertexDictionary(); foreach (IVertex v in VisitedGraph.Vertices) { //Handle self-loops foreach (IEdge a in VisitedGraph.OutEdges(v)) if (a.Target == v) ResidualCapacities[a] = Capacities[a]; //Initialize Colors[v] = GraphColor.White; parents[v] = v; current[v] = 0; } // eliminate flow cycles and topologically order the vertices IVertexEnumerator vertices = VisitedGraph.Vertices.GetEnumerator(); while (vertices.MoveNext()) { u = vertices.Current; if (Colors[u] == GraphColor.White && excessFlow[u] > 0 && u != src && u != sink) { r = u; Colors[r] = GraphColor.Gray; while(true) { for (; current[u] < VisitedGraph.OutDegree(u); ++current[u]) { IEdge a = VisitedGraph.OutEdges(u)[current[u]]; if (Capacities[a] == 0 && IsResidualEdge(a)) { IVertex v = a.Target; if (Colors[v] == GraphColor.White) { Colors[v] = GraphColor.Gray; parents[v] = u; u = v; break; } else if (Colors[v] == GraphColor.Gray) { //find minimum flow on the cycle double delta = ResidualCapacities[a]; while (true) { IEdge e = VisitedGraph.OutEdges(v)[current[v]]; delta = Math.Min(delta, ResidualCapacities[e]); if (v == u) break; else v = e.Target; } //remove delta flow units v = u; while (true) { a = VisitedGraph.OutEdges(v)[current[v]]; ResidualCapacities[a] -= delta; ResidualCapacities[ReversedEdges[a]] += delta; v = a.Target; if (v == u) break; } // back-out of DFS to the first saturated edge restart = u; for (v = VisitedGraph.OutEdges(u)[current[u]].Target; v != u; v = a.Target) { a = VisitedGraph.OutEdges(v)[current[v]]; if (Colors[v] == GraphColor.White || IsSaturated(a)) { Colors[VisitedGraph.OutEdges(v)[current[v]].Target] = GraphColor.White; if (Colors[v] != GraphColor.White) restart = v; } } if (restart != u) { u = restart; ++current[u]; break; } } } } if (current[u] == VisitedGraph.OutDegree(u)) { // scan of i is complete Colors[u] = GraphColor.Black; if (u != src) { if (bos == null) { bos = u; tos = u; } else { topoNext[u] = tos; tos = u; } } if (u != r) { u = parents[u]; ++current[u]; } else break; } } } } // return excess flows // note that the sink is not on the stack if (bos != null) { IEdgeEnumerator ai; for (u = tos; u != bos; u = topoNext[u]) { ai = VisitedGraph.OutEdges(u).GetEnumerator(); while (excessFlow[u] > 0 && ai.MoveNext()) { if (Capacities[ai.Current] == 0 && IsResidualEdge(ai.Current)) PushFlow(ai.Current); } } // do the bottom u = bos; ai = VisitedGraph.OutEdges(u).GetEnumerator(); while (excessFlow[u] > 0 && ai.MoveNext()) { if (Capacities[ai.Current] == 0 && IsResidualEdge(ai.Current)) PushFlow(ai.Current); } } }
private void ConvertPreflowToFlow() { IVertex vertex3; IVertex vertex4 = null; IVertex vertex5 = null; VertexVertexDictionary dictionary = new VertexVertexDictionary(); VertexVertexDictionary dictionary2 = new VertexVertexDictionary(); IVertexEnumerator enumerator3 = this.VisitedGraph.get_Vertices().GetEnumerator(); while (enumerator3.MoveNext()) { IVertex vertex6 = enumerator3.get_Current(); IEdgeEnumerator enumerator4 = this.VisitedGraph.OutEdges(vertex6).GetEnumerator(); while (enumerator4.MoveNext()) { IEdge edge = enumerator4.get_Current(); if (edge.get_Target() == vertex6) { base.ResidualCapacities.set_Item(edge, base.Capacities.get_Item(edge)); } } base.Colors.set_Item(vertex6, 0); dictionary.set_Item(vertex6, vertex6); this.current.set_Item(vertex6, 0); } IVertexEnumerator enumerator = this.VisitedGraph.get_Vertices().GetEnumerator(); while (enumerator.MoveNext()) { vertex3 = enumerator.get_Current(); if (((base.Colors.get_Item(vertex3) != null) || (this.excessFlow.get_Item(vertex3) <= 0.0)) || ((vertex3 == this.src) || (vertex3 == this.sink))) { continue; } IVertex vertex = vertex3; base.Colors.set_Item(vertex, 2); Label_0392: do { while (this.current.get_Item(vertex3) < this.VisitedGraph.OutDegree(vertex3)) { VertexIntDictionary dictionary6; IVertex vertex9; IEdge a = this.VisitedGraph.OutEdges(vertex3).get_Item(this.current.get_Item(vertex3)); if ((base.Capacities.get_Item(a) == 0.0) && this.IsResidualEdge(a)) { IVertex vertex7 = a.get_Target(); if (base.Colors.get_Item(vertex7) == null) { base.Colors.set_Item(vertex7, 2); dictionary.set_Item(vertex7, vertex3); vertex3 = vertex7; break; } if (base.Colors.get_Item(vertex7) == 2) { double num = base.ResidualCapacities.get_Item(a); while (true) { IEdge edge3 = this.VisitedGraph.OutEdges(vertex7).get_Item(this.current.get_Item(vertex7)); num = Math.Min(num, base.ResidualCapacities.get_Item(edge3)); if (vertex7 == vertex3) { break; } vertex7 = edge3.get_Target(); } vertex7 = vertex3; do { EdgeDoubleDictionary dictionary3; IEdge edge4; EdgeDoubleDictionary dictionary4; IEdge edge5; a = this.VisitedGraph.OutEdges(vertex7).get_Item(this.current.get_Item(vertex7)); (dictionary3 = base.ResidualCapacities).set_Item(edge4 = a, dictionary3.get_Item(edge4) - num); (dictionary4 = base.ResidualCapacities).set_Item(edge5 = base.ReversedEdges.get_Item(a), dictionary4.get_Item(edge5) + num); vertex7 = a.get_Target(); } while (vertex7 != vertex3); IVertex vertex2 = vertex3; for (vertex7 = this.VisitedGraph.OutEdges(vertex3).get_Item(this.current.get_Item(vertex3)).get_Target(); vertex7 != vertex3; vertex7 = a.get_Target()) { a = this.VisitedGraph.OutEdges(vertex7).get_Item(this.current.get_Item(vertex7)); if ((base.Colors.get_Item(vertex7) == null) || this.IsSaturated(a)) { base.Colors.set_Item(this.VisitedGraph.OutEdges(vertex7).get_Item(this.current.get_Item(vertex7)).get_Target(), 0); if (base.Colors.get_Item(vertex7) != null) { vertex2 = vertex7; } } } if (vertex2 != vertex3) { VertexIntDictionary dictionary5; IVertex vertex8; vertex3 = vertex2; (dictionary5 = this.current).set_Item(vertex8 = vertex3, dictionary5.get_Item(vertex8) + 1); break; } } } (dictionary6 = this.current).set_Item(vertex9 = vertex3, dictionary6.get_Item(vertex9) + 1); } } while (this.current.get_Item(vertex3) != this.VisitedGraph.OutDegree(vertex3)); base.Colors.set_Item(vertex3, 1); if (vertex3 != this.src) { if (vertex4 == null) { vertex4 = vertex3; vertex5 = vertex3; } else { dictionary2.set_Item(vertex3, vertex5); vertex5 = vertex3; } } if (vertex3 != vertex) { VertexIntDictionary dictionary7; IVertex vertex10; vertex3 = dictionary.get_Item(vertex3); (dictionary7 = this.current).set_Item(vertex10 = vertex3, dictionary7.get_Item(vertex10) + 1); goto Label_0392; } } if (vertex4 != null) { IEdgeEnumerator enumerator2; for (vertex3 = vertex5; vertex3 != vertex4; vertex3 = dictionary2.get_Item(vertex3)) { enumerator2 = this.VisitedGraph.OutEdges(vertex3).GetEnumerator(); while ((this.excessFlow.get_Item(vertex3) > 0.0) && enumerator2.MoveNext()) { if ((base.Capacities.get_Item(enumerator2.get_Current()) == 0.0) && this.IsResidualEdge(enumerator2.get_Current())) { this.PushFlow(enumerator2.get_Current()); } } } vertex3 = vertex4; enumerator2 = this.VisitedGraph.OutEdges(vertex3).GetEnumerator(); while ((this.excessFlow.get_Item(vertex3) > 0.0) && enumerator2.MoveNext()) { if ((base.Capacities.get_Item(enumerator2.get_Current()) == 0.0) && this.IsResidualEdge(enumerator2.get_Current())) { this.PushFlow(enumerator2.get_Current()); } } } }