/// <summary> /// This is the core part of the algorithm, "phase one." /// </summary> /// <returns></returns> private double MaximumPreflow() { workSinceLastUpdate = 0; while (maxActive >= minActive) // "main" loop { PreflowLayer layer = layers[maxActive]; if (layer.ActiveVertices.Count == 0) { --maxActive; } else { IVertex u = layer.ActiveVertices[0]; RemoveFromActiveList(u); Discharge(u); if (workSinceLastUpdate * globalUpdateFrequency > nm) { GlobalDistanceUpdate(); workSinceLastUpdate = 0; } } } return(excessFlow[sink]); }
//======================================================================= // This function is called "push" in Goldberg's h_prf implementation, // but it is called "discharge" in the paper and in hi_pr.c. private void Discharge(IVertex u) { while (true) { int ai; for (ai = current[u]; ai < VisitedGraph.OutDegree(u); ai++) { IEdge a = VisitedGraph.OutEdges(u)[ai]; if (IsResidualEdge(a)) { IVertex v = a.Target; if (IsAdmissible(u, v)) { if (v != sink && excessFlow[v] == 0) { RemoveFromInactiveList(v); AddToActiveList(v, layers[distances[v]]); } PushFlow(a); if (excessFlow[u] == 0) { break; } } } } PreflowLayer layer = layers[distances[u]]; int du = distances[u]; if (ai == VisitedGraph.OutDegree(u)) // i must be relabeled { RelabelDistance(u); if (layer.ActiveVertices.Count == 0 && layer.InactiveVertices.Count == 0) { Gap(du); } if (distances[u] == n) { break; } } else { // i is no longer active current[u] = ai; AddToInactiveList(u, layer); break; } } }
private void Initialize() { int m = 0; n = VisitedGraph.VerticesCount; foreach (IVertex u in VisitedGraph.Vertices) m += VisitedGraph.OutDegree(u); // Don't count the reverse edges m /= 2; nm = alpha * n + m; excessFlow.Clear(); current.Clear(); distances.Clear(); layers = new PreflowLayer[n]; for (int i = 0; i < n; i++) layers[i] = new PreflowLayer(); // Initialize flow to zero which means initializing // the residual capacity to equal the capacity. foreach (IVertex u in VisitedGraph.Vertices) { foreach (IEdge e in VisitedGraph.OutEdges(u)) this.ResidualCapacities[e] = this.Capacities[e]; excessFlow[u] = 0; current[u] = 0; } bool overflowDetected = false; double testExcess = 0; foreach (IEdge a in VisitedGraph.OutEdges(src)) { if (a.Target != src) testExcess += this.ResidualCapacities[a]; } if (testExcess >= double.MaxValue || double.IsPositiveInfinity(testExcess)) overflowDetected = true; if (overflowDetected) { excessFlow[src] = double.MaxValue; } else { excessFlow[src] = 0; foreach (IEdge a in this.VisitedGraph.OutEdges(src)) { if (a.Target != src) { double delta = this.ResidualCapacities[a]; this.ResidualCapacities[a] -= delta; this.ResidualCapacities[this.ReversedEdges[a]] += delta; this.excessFlow[a.Target] += delta; } } } maxDistance = VisitedGraph.VerticesCount - 1; maxActive = 0; minActive = n; foreach (IVertex u in this.VisitedGraph.Vertices) { if (u == sink) { distances[u] = 0; continue; } else if (u == src && !overflowDetected) { distances[u] = n; } else { distances[u] = 1; } if (excessFlow[u] > 0) this.AddToActiveList(u, layers[1]); else if (distances[u] < n) this.AddToInactiveList(u, layers[1]); } }
private void AddToInactiveList(IVertex u, PreflowLayer layer) { layer.InactiveVertices.Insert(0, u); }
private void AddToActiveList(IVertex u, PreflowLayer layer) { layer.ActiveVertices.Insert(0, u); maxActive = Math.Max(Distances[u], maxActive); minActive = Math.Min(Distances[u], minActive); }
private void Initialize() { int m = 0; n = VisitedGraph.VerticesCount; foreach (IVertex u in VisitedGraph.Vertices) { m += VisitedGraph.OutDegree(u); } // Don't count the reverse edges m /= 2; nm = alpha * n + m; excessFlow.Clear(); current.Clear(); distances.Clear(); layers = new PreflowLayer[n]; for (int i = 0; i < n; i++) { layers[i] = new PreflowLayer(); } // Initialize flow to zero which means initializing // the residual capacity to equal the capacity. foreach (IVertex u in VisitedGraph.Vertices) { foreach (IEdge e in VisitedGraph.OutEdges(u)) { this.ResidualCapacities[e] = this.Capacities[e]; } excessFlow[u] = 0; current[u] = 0; } bool overflowDetected = false; double testExcess = 0; foreach (IEdge a in VisitedGraph.OutEdges(src)) { if (a.Target != src) { testExcess += this.ResidualCapacities[a]; } } if (testExcess >= double.MaxValue || double.IsPositiveInfinity(testExcess)) { overflowDetected = true; } if (overflowDetected) { excessFlow[src] = double.MaxValue; } else { excessFlow[src] = 0; foreach (IEdge a in this.VisitedGraph.OutEdges(src)) { if (a.Target != src) { double delta = this.ResidualCapacities[a]; this.ResidualCapacities[a] -= delta; this.ResidualCapacities[this.ReversedEdges[a]] += delta; this.excessFlow[a.Target] += delta; } } } maxDistance = VisitedGraph.VerticesCount - 1; maxActive = 0; minActive = n; foreach (IVertex u in this.VisitedGraph.Vertices) { if (u == sink) { distances[u] = 0; continue; } else if (u == src && !overflowDetected) { distances[u] = n; } else { distances[u] = 1; } if (excessFlow[u] > 0) { this.AddToActiveList(u, layers[1]); } else if (distances[u] < n) { this.AddToInactiveList(u, layers[1]); } } }
private void AddToActiveList(IVertex u, PreflowLayer layer) { layer.ActiveVertices.Insert(0, u); this.maxActive = Math.Max(this.Distances.get_Item(u), this.maxActive); this.minActive = Math.Min(this.Distances.get_Item(u), this.minActive); }