LCOV - code coverage report
Current view: top level - app/src/Alg/Flow - EdmondsKarp.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 42 60 70.0 %
Date: 2023-08-17 16:45:52 Functions: 5 7 71.4 %

          Line data    Source code
       1             : #include "Alg/Flow/EdmondsKarp.hpp"
       2             : 
       3             : #include <unordered_set>
       4             : 
       5             : #include "Alg/Graph.hpp"
       6             : 
       7             : using namespace std;
       8             : using namespace Alg;
       9             : using namespace Alg::Flow;
      10             : 
      11             : typedef Graph::Node  Node;
      12             : typedef Graph::Edge  Edge;
      13             : typedef Edge::Weight Weight;
      14             : typedef Graph::Path  Path;
      15             : 
      16     1087340 : void EdmondsKarp::EGraph::addEdge(Edge::ID id, Node u, Node v, Edge::Weight c) {
      17     1087340 :     Graph::addEdge(id, u, v, c);
      18     1087340 :     if(edges.size() <= size_t(id))
      19      375112 :         edges.resize(id + 1);
      20     1087340 :     edges.at(id) = {u, getAdj(u).size() - 1};
      21     1087340 : }
      22             : 
      23     1014760 : Edge &EdmondsKarp::EGraph::getEdge(Edge::ID id) {
      24     1014760 :     const auto &[u, i] = edges.at(id);
      25     1014760 :     return getAdj(u).at(i);
      26             : }
      27             : 
      28       93778 : EdmondsKarp::EdmondsKarp(ShortestPath::ShortestPathOneOne &sp_):
      29       93778 :     sp(sp_) {}
      30             : 
      31       93778 : void EdmondsKarp::buildResidualGraph(const Graph &G) {
      32       93778 :     Gf = EGraph();
      33             : 
      34      686793 :     for(const Node &u: G.getNodes()) {
      35      593015 :         Gf.addNode(u);
      36     1136680 :         for(const Edge &e: G.getAdj(u)) {
      37      543669 :             size_t eid1 = (size_t(e.id) << 1);
      38      543669 :             size_t eid2 = (size_t(e.id) << 1) | 1;
      39             :             // clang-format off
      40      543669 :             Gf.addEdge((Edge::ID)eid1, e.u, e.v, e.w);
      41      543669 :             Gf.addEdge((Edge::ID)eid2, e.v, e.u, 0.0);
      42             :             // clang-format on
      43             :         }
      44             :     }
      45       93778 : }
      46             : 
      47      114545 : Weight getBottleneck(const Path &path) {
      48      114545 :     Weight bottleneck = Edge::WEIGHT_INF;
      49      621926 :     for(const Edge &e: path) {
      50      644407 :         bottleneck = min(bottleneck, e.w);
      51             :     }
      52      114545 :     return bottleneck;
      53             : }
      54             : 
      55       93778 : Weight EdmondsKarp::solve(
      56             :     const Graph &G,
      57             :     Node         source,
      58             :     Node         sink
      59             : ) {
      60       93778 :     originalGraph = &G;
      61             : 
      62       93778 :     buildResidualGraph(G);
      63             : 
      64       93778 :     Weight totalFlow = 0.0;
      65             : 
      66      208323 :     while(true) {
      67      208323 :         sp.solveStartFinish(Gf, source, sink);
      68      208323 :         if(!sp.hasVisited(sink))
      69             :             break;
      70             : 
      71      229090 :         Path   path = sp.getPath(sink);
      72      114545 :         Weight f    = getBottleneck(path);
      73      114545 :         if(f <= 0.0)
      74             :             break;
      75             : 
      76      114545 :         totalFlow += f;
      77             : 
      78      621926 :         for(const Edge &e: path) {
      79      507381 :             Edge::ID oppositeID = e.id ^ 1;
      80             : 
      81      507381 :             Gf.getEdge(e.id).w -= f;
      82      507381 :             Gf.getEdge(oppositeID).w += f;
      83             :         }
      84             :     }
      85             : 
      86       93778 :     return totalFlow;
      87             : }
      88             : 
      89           0 : Graph EdmondsKarp::getFlowsGraph() const {
      90           0 :     unordered_set<Edge::ID> edgeIDs;
      91           0 :     for(const Node &u: originalGraph->getNodes()) {
      92           0 :         for(const Edge &e: originalGraph->getAdj(u)) {
      93           0 :             edgeIDs.insert(e.id);
      94             :         }
      95             :     }
      96             : 
      97           0 :     unordered_map<Edge::ID, Weight> flows;
      98           0 :     for(const Node &u: Gf.getNodes()) {
      99           0 :         for(const Edge &e: Gf.getAdj(u)) {
     100           0 :             Edge::ID eid      = e.id >> 1;
     101           0 :             bool     backward = (e.id & 1);
     102           0 :             if(backward && edgeIDs.count(eid)) {
     103           0 :                 flows[e.id] = e.w;
     104             :             }
     105             :         }
     106             :     }
     107             : 
     108           0 :     Graph G;
     109           0 :     for(const Node &u: originalGraph->getNodes()) {
     110           0 :         G.addNode(u);
     111           0 :         for(const Edge &e: originalGraph->getAdj(u)) {
     112           0 :             G.addEdge(e.id, e.u, e.v, flows.at(e.id));
     113             :         }
     114             :     }
     115             : 
     116           0 :     return G;
     117             : }

Generated by: LCOV version 1.14