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

#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 hugo;

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

int main(int, char** argv) {

  std::string in=argv[1];
  typedef ListGraph MutableGraph;

  {
    typedef ListGraph Graph;
    typedef Graph::Node Node;
    typedef Graph::EdgeIt EdgeIt;

    Graph G;
    Node s, t;
    Graph::EdgeMap<int> cap(G);
    std::ifstream ins(in.c_str());
    readDimacsMaxFlow(ins, G, s, t, cap);

    {
      std::cout << "ListGraph..." << std::endl;
      std::cout << "edmonds karp demo (physical blocking flow augmentation)..." << std::endl;
      Graph::EdgeMap<int> flow(G); //0 flow

      Timer ts;
      ts.reset();

      MaxFlow<Graph, int, Graph::EdgeMap<int>, Graph::EdgeMap<int> > max_flow_test(G, s, t, flow, cap);
      int 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 (on-the-fly blocking flow augmentation)..." << std::endl;
      Graph::EdgeMap<int> flow(G); //0 flow

      Timer ts;
      ts.reset();

      MaxFlow<Graph, int, Graph::EdgeMap<int>, Graph::EdgeMap<int> > max_flow_test(G, s, t, flow, cap);
      int 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;
      Graph::EdgeMap<int> flow(G); //0 flow

      Timer ts;
      ts.reset();

      MaxFlow<Graph, int, Graph::EdgeMap<int>, Graph::EdgeMap<int> > max_flow_test(G, s, t, flow, cap);
      int 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 SmartGraph Graph;
    typedef Graph::Node Node;
    typedef Graph::EdgeIt EdgeIt;

    Graph G;
    Node s, t;
    Graph::EdgeMap<int> cap(G);
    std::ifstream ins(in.c_str());
    readDimacsMaxFlow(ins, G, s, t, cap);

    {
      std::cout << "SmartGraph..." << std::endl;
      std::cout << "edmonds karp demo (physical blocking flow augmentation)..." << std::endl;
      Graph::EdgeMap<int> flow(G); //0 flow

      Timer ts;
      ts.reset();

      MaxFlow<Graph, int, Graph::EdgeMap<int>, Graph::EdgeMap<int> > max_flow_test(G, s, t, flow, cap);
      int 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 (on-the-fly blocking flow augmentation)..." << std::endl;
      Graph::EdgeMap<int> flow(G); //0 flow

      Timer ts;
      ts.reset();

      MaxFlow<Graph, int, Graph::EdgeMap<int>, Graph::EdgeMap<int> > max_flow_test(G, s, t, flow, cap);
      int 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;
      Graph::EdgeMap<int> flow(G); //0 flow

      Timer ts;
      ts.reset();

      MaxFlow<Graph, int, Graph::EdgeMap<int>, Graph::EdgeMap<int> > max_flow_test(G, s, t, flow, cap);
      int 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;
}
