/networkit/cpp/flow/EdmondsKarp.cpp

https://github.com/kit-parco/networkit · C++ · 126 lines · 95 code · 23 blank · 8 comment · 22 complexity · 216e87d18c110d8245cb700d8e099b3a MD5 · raw file

  1. /*
  2. * EdmondsKarp.cpp
  3. *
  4. * Created on: 11.06.2014
  5. * Authors: Michael Wegner <michael.wegner@student.kit.edu>
  6. * Michael Hamann <michael.hamann@kit.edu>
  7. */
  8. #include <algorithm>
  9. #include <limits>
  10. #include <stdexcept>
  11. #include <networkit/flow/EdmondsKarp.hpp>
  12. namespace NetworKit {
  13. EdmondsKarp::EdmondsKarp(const Graph &graph, node source, node sink) : graph(&graph), source(source), sink(sink) {}
  14. edgeweight EdmondsKarp::BFS(std::vector<edgeweight> &residFlow, std::vector<node> &pred) const {
  15. std::fill(pred.begin(), pred.end(), none);
  16. pred.resize(graph->upperNodeIdBound(), none);
  17. std::vector<edgeweight> gain(graph->upperNodeIdBound(), 0);
  18. std::queue<node> Q;
  19. Q.push(source);
  20. pred[source] = source;
  21. gain[source] = std::numeric_limits<edgeweight>::max();
  22. do {
  23. node u = Q.front();
  24. Q.pop();
  25. bool sinkReached = false;
  26. graph->forNeighborsOf(u, [&](node, node v, edgeweight weight, edgeid eid){
  27. if ((
  28. (u >= v && flow[eid] < weight) || (u < v && residFlow[eid] < weight)
  29. )&& pred[v] == none) { // only add those neighbors with rest capacity and which were not discovered yet
  30. pred[v] = u;
  31. gain[v] = std::min(gain[u], weight - (u >= v ? flow[eid] : residFlow[eid]));
  32. if (v != sink && !sinkReached) {
  33. Q.push(v);
  34. } else {
  35. sinkReached = true;
  36. }
  37. }
  38. });
  39. if (sinkReached) {
  40. return gain[sink];
  41. }
  42. } while (!Q.empty());
  43. return 0.0;
  44. }
  45. void EdmondsKarp::run() {
  46. if (!graph->hasEdgeIds()) { throw std::runtime_error("edges have not been indexed - call indexEdges first"); }
  47. flow.clear();
  48. flow.resize(graph->upperEdgeIdBound(), 0.0);
  49. std::vector<edgeweight> residFlow(graph->upperEdgeIdBound(), 0.0);
  50. flowValue = 0;
  51. do {
  52. std::vector<node> pred;
  53. edgeweight gain = BFS(residFlow, pred);
  54. if (gain == 0) break;
  55. flowValue += gain;
  56. node v = sink;
  57. while (v != source) {
  58. node u = pred[v];
  59. edgeid eid = graph->edgeId(u, v);
  60. if (u >= v) {
  61. flow[eid] += gain;
  62. residFlow[eid] -= gain;
  63. } else {
  64. flow[eid] -= gain;
  65. residFlow[eid] += gain;
  66. }
  67. v = u;
  68. }
  69. } while (true);
  70. graph->parallelForEdges([&](node, node, edgeid eid) {
  71. flow[eid] = std::max(flow[eid], residFlow[eid]);
  72. });
  73. }
  74. edgeweight EdmondsKarp::getMaxFlow() const {
  75. return flowValue;
  76. }
  77. std::vector<node> EdmondsKarp::getSourceSet() const {
  78. // perform bfs from source
  79. std::vector<bool> visited(graph->upperNodeIdBound(), false);
  80. std::vector<node> sourceSet;
  81. std::queue<node> Q;
  82. Q.push(source);
  83. visited[source] = true;
  84. while (!Q.empty()) {
  85. node u = Q.front();
  86. Q.pop();
  87. sourceSet.push_back(u);
  88. graph->forNeighborsOf(u, [&](node, node v, edgeweight weight, edgeid eid) {
  89. if (!visited[v] && flow[eid] < weight) {
  90. Q.push(v);
  91. visited[v] = true;
  92. }
  93. });
  94. }
  95. return sourceSet;
  96. }
  97. edgeweight EdmondsKarp::getFlow(node u, node v) const {
  98. return flow[graph->edgeId(u, v)];
  99. }
  100. std::vector<edgeweight> EdmondsKarp::getFlowVector() const {
  101. return flow;
  102. }
  103. } /* namespace NetworKit */