marci@764: // -*- c++ -*- marci@764: #include marci@764: #include marci@764: alpar@921: #include marci@1014: #include alpar@921: #include alpar@921: #include marci@764: //#include marci@1014: #include marci@764: #include marci@764: //#include marci@764: #include marci@764: marci@764: // Use a DIMACS max flow file as stdin. marci@764: // max_flow_demo < dimacs_max_flow_file marci@764: marci@1015: using namespace lemon; marci@1015: marci@1015: namespace lemon { marci@1015: marci@1015: template marci@1015: class PrimalMap { marci@1015: protected: marci@1015: LPSolverWrapper* lp; marci@1015: EdgeIndexMap* edge_index_map; marci@1015: public: marci@1015: PrimalMap(LPSolverWrapper& _lp, EdgeIndexMap& _edge_index_map) : marci@1015: lp(&_lp), edge_index_map(&_edge_index_map) { } marci@1015: double operator[](Edge e) const { marci@1015: return lp->getPrimal((*edge_index_map)[e]); marci@1015: } marci@1015: }; marci@1015: marci@1015: // excess: rho-delta marci@1015: template , marci@1015: typename LCapMap=typename Graph::template EdgeMap, marci@1015: typename CapMap=typename Graph::template EdgeMap, marci@1015: typename FlowMap=typename Graph::template EdgeMap, marci@1015: typename CostMap=typename Graph::template EdgeMap > marci@1015: class MinCostGenFlow { marci@1015: protected: marci@1015: const Graph& g; marci@1015: const Excess& excess; marci@1015: const LCapMap& lcapacity; marci@1015: const CapMap& capacity; marci@1015: FlowMap& flow; marci@1015: const CostMap& cost; marci@1015: public: marci@1015: MinCostGenFlow(const Graph& _g, const Excess& _excess, marci@1015: const LCapMap& _lcapacity, const CapMap& _capacity, marci@1015: FlowMap& _flow, marci@1015: const CostMap& _cost) : marci@1015: g(_g), excess(_excess), lcapacity(_lcapacity), marci@1015: capacity(_capacity), flow(_flow), cost(_cost) { } marci@1015: void run() { marci@1015: LPSolverWrapper lp; marci@1015: lp.setMinimize(); marci@1015: typedef LPSolverWrapper::ColIt ColIt; marci@1015: typedef LPSolverWrapper::RowIt RowIt; marci@1015: typedef typename Graph::template EdgeMap EdgeIndexMap; marci@1015: EdgeIndexMap edge_index_map(g); marci@1015: PrimalMap lp_flow(lp, edge_index_map); marci@1015: for (typename Graph::EdgeIt e(g); e!=INVALID; ++e) { marci@1015: ColIt col_it=lp.addCol(); marci@1015: edge_index_map.set(e, col_it); marci@1015: if (lcapacity[e]==capacity[e]) marci@1015: lp.setColBounds(col_it, LPX_FX, lcapacity[e], capacity[e]); marci@1015: else marci@1015: lp.setColBounds(col_it, LPX_DB, lcapacity[e], capacity[e]); marci@1015: lp.setObjCoef(col_it, cost[e]); marci@1015: } marci@1015: for (typename Graph::NodeIt n(g); n!=INVALID; ++n) { marci@1015: typename Graph::template EdgeMap coeffs(g, 0); marci@1015: for (typename Graph::InEdgeIt e(g, n); e!=INVALID; ++e) marci@1015: coeffs.set(e, coeffs[e]+1); marci@1015: for (typename Graph::OutEdgeIt e(g, n); e!=INVALID; ++e) marci@1015: coeffs.set(e, coeffs[e]-1); marci@1015: RowIt row_it=lp.addRow(); marci@1015: typename std::vector< std::pair > row; marci@1015: //std::cout << "node:" < cap(g); marci@764: //readDimacsMaxFlow(std::cin, g, s, t, cap); marci@764: readDimacs(std::cin, g, cap, s, t); marci@764: Timer ts; marci@764: Graph::EdgeMap flow(g); //0 flow marci@1014: Preflow, Graph::EdgeMap > marci@764: max_flow_test(g, s, t, cap, flow); marci@764: AugmentingFlow, Graph::EdgeMap > marci@764: augmenting_flow_test(g, s, t, cap, flow); marci@764: marci@764: Graph::NodeMap cut(g); marci@764: marci@764: { marci@764: std::cout << "preflow ..." << std::endl; marci@764: ts.reset(); marci@764: max_flow_test.run(); marci@764: std::cout << "elapsed time: " << ts << std::endl; marci@764: std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl; marci@1014: max_flow_test.minCut(cut); marci@764: marci@1015: for (EdgeIt e(g); e!=INVALID; ++e) { alpar@986: if (cut[g.source(e)] && !cut[g.target(e)] && !flow[e]==cap[e]) marci@764: std::cout << "Slackness does not hold!" << std::endl; alpar@986: if (!cut[g.source(e)] && cut[g.target(e)] && flow[e]>0) marci@764: std::cout << "Slackness does not hold!" << std::endl; marci@764: } marci@764: } marci@764: marci@764: // { marci@764: // std::cout << "preflow ..." << std::endl; marci@764: // FOR_EACH_LOC(Graph::EdgeIt, e, g) flow.set(e, 0); marci@764: // ts.reset(); marci@1014: // max_flow_test.preflow(Preflow, Graph::EdgeMap >::GEN_FLOW); marci@764: // std::cout << "elapsed time: " << ts << std::endl; marci@764: // std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl; marci@764: marci@764: // FOR_EACH_LOC(Graph::EdgeIt, e, g) { alpar@986: // if (cut[g.source(e)] && !cut[g.target(e)] && !flow[e]==cap[e]) marci@764: // std::cout << "Slackness does not hold!" << std::endl; alpar@986: // if (!cut[g.source(e)] && cut[g.target(e)] && flow[e]>0) marci@764: // std::cout << "Slackness does not hold!" << std::endl; marci@764: // } marci@764: // } marci@764: marci@764: // { marci@764: // std::cout << "wrapped preflow ..." << std::endl; marci@764: // FOR_EACH_LOC(Graph::EdgeIt, e, g) flow.set(e, 0); marci@764: // ts.reset(); marci@764: // pre_flow_res.run(); marci@764: // std::cout << "elapsed time: " << ts << std::endl; marci@764: // std::cout << "flow value: "<< pre_flow_test.flowValue() << std::endl; marci@764: // } marci@764: marci@764: { marci@764: std::cout << "physical blocking flow augmentation ..." << std::endl; marci@1015: for (EdgeIt e(g); e!=INVALID; ++e) flow.set(e, 0); marci@764: ts.reset(); marci@764: int i=0; marci@764: while (augmenting_flow_test.augmentOnBlockingFlow()) { ++i; } marci@764: std::cout << "elapsed time: " << ts << std::endl; marci@764: std::cout << "number of augmentation phases: " << i << std::endl; marci@764: std::cout << "flow value: "<< augmenting_flow_test.flowValue() << std::endl; marci@764: marci@1015: for (EdgeIt e(g); e!=INVALID; ++e) { alpar@986: if (cut[g.source(e)] && !cut[g.target(e)] && !flow[e]==cap[e]) marci@764: std::cout << "Slackness does not hold!" << std::endl; alpar@986: if (!cut[g.source(e)] && cut[g.target(e)] && flow[e]>0) marci@764: std::cout << "Slackness does not hold!" << std::endl; marci@764: } marci@764: } marci@764: marci@764: // { marci@764: // std::cout << "faster physical blocking flow augmentation ..." << std::endl; marci@764: // FOR_EACH_LOC(Graph::EdgeIt, e, g) flow.set(e, 0); marci@764: // ts.reset(); marci@764: // int i=0; marci@764: // while (max_flow_test.augmentOnBlockingFlow1()) { ++i; } marci@764: // std::cout << "elapsed time: " << ts << std::endl; marci@764: // std::cout << "number of augmentation phases: " << i << std::endl; marci@764: // std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl; marci@764: // } marci@764: marci@764: { marci@764: std::cout << "on-the-fly blocking flow augmentation ..." << std::endl; marci@1015: for (EdgeIt e(g); e!=INVALID; ++e) flow.set(e, 0); marci@764: ts.reset(); marci@764: int i=0; marci@764: while (augmenting_flow_test.augmentOnBlockingFlow2()) { ++i; } marci@764: std::cout << "elapsed time: " << ts << std::endl; marci@764: std::cout << "number of augmentation phases: " << i << std::endl; marci@764: std::cout << "flow value: "<< augmenting_flow_test.flowValue() << std::endl; marci@764: marci@1015: for (EdgeIt e(g); e!=INVALID; ++e) { alpar@986: if (cut[g.source(e)] && !cut[g.target(e)] && !flow[e]==cap[e]) marci@764: std::cout << "Slackness does not hold!" << std::endl; alpar@986: if (!cut[g.source(e)] && cut[g.target(e)] && flow[e]>0) marci@764: std::cout << "Slackness does not hold!" << std::endl; marci@764: } marci@764: } marci@764: marci@764: // { marci@764: // std::cout << "on-the-fly shortest path augmentation ..." << std::endl; marci@764: // FOR_EACH_LOC(Graph::EdgeIt, e, g) flow.set(e, 0); marci@764: // ts.reset(); marci@764: // int i=0; marci@764: // while (augmenting_flow_test.augmentOnShortestPath()) { ++i; } marci@764: // std::cout << "elapsed time: " << ts << std::endl; marci@764: // std::cout << "number of augmentation phases: " << i << std::endl; marci@764: // std::cout << "flow value: "<< augmenting_flow_test.flowValue() << std::endl; marci@764: marci@764: // FOR_EACH_LOC(Graph::EdgeIt, e, g) { alpar@986: // if (cut[g.source(e)] && !cut[g.target(e)] && !flow[e]==cap[e]) marci@764: // std::cout << "Slackness does not hold!" << std::endl; alpar@986: // if (!cut[g.source(e)] && cut[g.target(e)] && flow[e]>0) marci@764: // std::cout << "Slackness does not hold!" << std::endl; marci@764: // } marci@764: // } marci@764: marci@764: // { marci@764: // std::cout << "on-the-fly shortest path augmentation ..." << std::endl; marci@764: // FOR_EACH_LOC(Graph::EdgeIt, e, g) flow.set(e, 0); marci@764: // ts.reset(); marci@764: // int i=0; marci@764: // while (augmenting_flow_test.augmentOnShortestPath2()) { ++i; } marci@764: // std::cout << "elapsed time: " << ts << std::endl; marci@764: // std::cout << "number of augmentation phases: " << i << std::endl; marci@764: // std::cout << "flow value: "<< augmenting_flow_test.flowValue() << std::endl; marci@764: marci@764: // FOR_EACH_LOC(Graph::EdgeIt, e, g) { alpar@986: // if (cut[g.source(e)] && !cut[g.target(e)] && !flow[e]==cap[e]) marci@764: // std::cout << "Slackness does not hold!" << std::endl; alpar@986: // if (!cut[g.source(e)] && cut[g.target(e)] && flow[e]>0) marci@764: // std::cout << "Slackness does not hold!" << std::endl; marci@764: // } marci@764: // } marci@764: marci@764: ts.reset(); marci@1015: marci@1015: Edge e=g.addEdge(t, s); marci@1015: Graph::EdgeMap cost(g, 0); marci@1015: cost.set(e, -1); marci@1015: cap.set(e, 10000); marci@1015: typedef ConstMap Excess; marci@1015: Excess excess(0); marci@1015: typedef ConstMap LCap; marci@1015: LCap lcap(0); marci@1015: marci@1015: MinCostGenFlow marci@1015: min_cost(g, excess, lcap, cap, flow, cost); marci@1015: min_cost.run(); marci@1015: marci@764: std::cout << "elapsed time: " << ts << std::endl; marci@1015: std::cout << "flow value: "<< flow[e] << std::endl; marci@764: }