// -*- c++ -*-
#include <iostream>
#include <fstream>

#include <list_graph.h>
#include <smart_graph.h>
#include <dimacs.h>
#include <edmonds_karp.h>
#include <time_measure.h>
#include <graph_wrapper.h>

using namespace lemon;

// Use a DIMACS max flow file as stdin.
// read_dimacs_demo < dimacs_max_flow_file

int main(int, char **) {

  typedef ListGraph MutableGraph;
  //typedef SmartGraph Graph;
  typedef ListGraph Graph;
  typedef Graph::Node Node;
  typedef Graph::EdgeIt EdgeIt;

  Graph G;
  Node s, t;
  Graph::EdgeMap<int> cap(G);
  readDimacsMaxFlow(std::cin, G, s, t, cap);

  {
    typedef TrivGraphWrapper<const Graph> GW;
    GW gw(G);
    typedef GW::EdgeMapWrapper< Graph::EdgeMap<int>, int > EMW;
    EMW cw(cap);
    Timer ts;
    GW::EdgeMap<int> flow(gw); 
    MaxFlow<GW, int, GW::EdgeMap<int>, EMW > max_flow_test(gw, s, t, flow, cw);
    int i;

    {
      std::cout << "edmonds karp demo (physical blocking flow augmentation)..." << std::endl;
      for (GW::EdgeIt e(gw); gw.valid(e); gw.next(e)) flow.set(e, 0);
      ts.reset();

      i=0;
      while (max_flow_test.augmentOnBlockingFlow<MutableGraph>()) { ++i; }

      std::cout << "elapsed time: " << ts << std::endl;
      std::cout << "number of augmentation phases: " << i << std::endl; 
      std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl;
    }

    {
      std::cout << "edmonds karp demo (physical blocking flow 1 augmentation)..." << std::endl;
      for (GW::EdgeIt e(gw); gw.valid(e); gw.next(e)) flow.set(e, 0);
      ts.reset();

      i=0;
      while (max_flow_test.augmentOnBlockingFlow1<MutableGraph>()) { ++i; }

      std::cout << "elapsed time: " << ts << std::endl;
      std::cout << "number of augmentation phases: " << i << std::endl; 
      std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl;
    }

    {
      std::cout << "edmonds karp demo (on-the-fly blocking flow augmentation)..." << std::endl;
      for (GW::EdgeIt e(gw); gw.valid(e); gw.next(e)) flow.set(e, 0);
      ts.reset();

      i=0;
      while (max_flow_test.augmentOnBlockingFlow2()) { ++i; }

      std::cout << "elapsed time: " << ts << std::endl;
      std::cout << "number of augmentation phases: " << i << std::endl; 
      std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl;
    }

    {
      std::cout << "edmonds karp demo (on-the-fly shortest path augmentation)..." << std::endl;
      for (GW::EdgeIt e(gw); gw.valid(e); gw.next(e)) flow.set(e, 0);
      ts.reset();

      i=0;
      while (max_flow_test.augmentOnShortestPath()) { ++i; }

      std::cout << "elapsed time: " << ts << std::endl;
      std::cout << "number of augmentation phases: " << i << std::endl; 
      std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl;
    }
  }




  {
    typedef TrivGraphWrapper<const Graph> GW1;
    GW1 gw1(G);
    typedef TrivGraphWrapper<const GW1> GW2;
    GW2 gw2(gw1);
    typedef TrivGraphWrapper<const GW2> GW3;
    GW3 gw3(gw2);
    typedef TrivGraphWrapper<const GW3> GW4;
    GW4 gw4(gw3);
    typedef TrivGraphWrapper<const GW4> GW5;
    GW5 gw5(gw4);
    typedef TrivGraphWrapper<const GW5> GW6;
    GW6 gw6(gw5);
    typedef TrivGraphWrapper<const GW6> GW7;
    GW7 gw7(gw6);
    typedef TrivGraphWrapper<const GW7> GW8;
    GW8 gw8(gw7);
    typedef TrivGraphWrapper<const GW8> GW9;
    GW9 gw9(gw8);
    typedef TrivGraphWrapper<const GW9> GW;
    GW gw(gw9);
    typedef GW::EdgeMapWrapper< Graph::EdgeMap<int>, int > EMW;
    EMW cw(cap);
    Timer ts;
    GW::EdgeMap<int> flow(gw); 
    MaxFlow<GW, int, GW::EdgeMap<int>, EMW > max_flow_test(gw, s, t, flow, cw);
    int i;

    {
      std::cout << "edmonds karp demo (physical blocking flow augmentation)..." << std::endl;
      for (GW::EdgeIt e(gw); gw.valid(e); gw.next(e)) flow.set(e, 0);
      ts.reset();

      i=0;
      while (max_flow_test.augmentOnBlockingFlow<MutableGraph>()) { ++i; }

      std::cout << "elapsed time: " << ts << std::endl;
      std::cout << "number of augmentation phases: " << i << std::endl; 
      std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl;
    }

    {
      std::cout << "edmonds karp demo (physical blocking flow 1 augmentation)..." << std::endl;
      for (GW::EdgeIt e(gw); gw.valid(e); gw.next(e)) flow.set(e, 0);
      ts.reset();

      i=0;
      while (max_flow_test.augmentOnBlockingFlow1<MutableGraph>()) { ++i; }

      std::cout << "elapsed time: " << ts << std::endl;
      std::cout << "number of augmentation phases: " << i << std::endl; 
      std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl;
    }

    {
      std::cout << "edmonds karp demo (on-the-fly blocking flow augmentation)..." << std::endl;
      for (GW::EdgeIt e(gw); gw.valid(e); gw.next(e)) flow.set(e, 0);
      ts.reset();

      i=0;
      while (max_flow_test.augmentOnBlockingFlow2()) { ++i; }

      std::cout << "elapsed time: " << ts << std::endl;
      std::cout << "number of augmentation phases: " << i << std::endl; 
      std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl;
    }

    {
      std::cout << "edmonds karp demo (on-the-fly shortest path augmentation)..." << std::endl;
      for (GW::EdgeIt e(gw); gw.valid(e); gw.next(e)) flow.set(e, 0);
      ts.reset();

      i=0;
      while (max_flow_test.augmentOnShortestPath()) { ++i; }

      std::cout << "elapsed time: " << ts << std::endl;
      std::cout << "number of augmentation phases: " << i << std::endl; 
      std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl;
    }
  }


  return 0;
}
