athos@610: // -*- c++ -*-
alpar@921: #ifndef LEMON_MINCOSTFLOW_H
alpar@921: #define LEMON_MINCOSTFLOW_H
athos@610: 
athos@610: ///\ingroup galgs
athos@610: ///\file
athos@645: ///\brief An algorithm for finding the minimum cost flow of given value in an uncapacitated network
athos@611: 
alpar@921: #include <lemon/dijkstra.h>
alpar@921: #include <lemon/graph_wrapper.h>
alpar@921: #include <lemon/maps.h>
athos@610: #include <vector>
athos@657: #include <list>
athos@662: #include <values.h>
alpar@921: #include <lemon/for_each_macros.h>
alpar@921: #include <lemon/unionfind.h>
alpar@921: #include <lemon/bin_heap.h>
athos@662: #include <bfs_dfs.h>
athos@610: 
alpar@921: namespace lemon {
athos@610: 
athos@610: /// \addtogroup galgs
athos@610: /// @{
athos@610: 
athos@661:   ///\brief Implementation of an algorithm for solving the minimum cost general
athos@661:   /// flow problem in an uncapacitated network
athos@610:   /// 
athos@610:   ///
alpar@921:   /// The class \ref lemon::MinCostFlow "MinCostFlow" implements
athos@633:   /// an algorithm for solving the following general minimum cost flow problem>
athos@633:   /// 
athos@633:   ///
athos@633:   ///
athos@633:   /// \warning It is assumed here that the problem has a feasible solution
athos@633:   ///
athos@661:   /// The range of the cost (weight) function is nonnegative reals but 
athos@610:   /// the range of capacity function is the set of nonnegative integers. 
athos@610:   /// It is not a polinomial time algorithm for counting the minimum cost
athos@610:   /// maximal flow, since it counts the minimum cost flow for every value 0..M
athos@610:   /// where \c M is the value of the maximal flow.
athos@610:   ///
athos@610:   ///\author Attila Bernath
athos@661:   template <typename Graph, typename CostMap, typename SupplyDemandMap>
athos@633:   class MinCostFlow {
athos@610: 
athos@661:     typedef typename CostMap::ValueType Cost;
athos@610: 
athos@633: 
athos@635:     typedef typename SupplyDemandMap::ValueType SupplyDemand;
athos@610:     
athos@610:     typedef typename Graph::Node Node;
athos@610:     typedef typename Graph::NodeIt NodeIt;
athos@610:     typedef typename Graph::Edge Edge;
athos@610:     typedef typename Graph::OutEdgeIt OutEdgeIt;
athos@661:     typedef typename Graph::template EdgeMap<SupplyDemand> FlowMap;
athos@661:     typedef ConstMap<Edge,SupplyDemand> ConstEdgeMap;
athos@610: 
athos@610:     //    typedef ConstMap<Edge,int> ConstMap;
athos@610: 
athos@661:     typedef ResGraphWrapper<const Graph,int,ConstEdgeMap,FlowMap> ResGraph;
athos@661:     typedef typename ResGraph::Edge ResGraphEdge;
athos@610: 
athos@661:     class ModCostMap {   
athos@661:       //typedef typename ResGraph::template NodeMap<Cost> NodeMap;
athos@661:       typedef typename Graph::template NodeMap<Cost> NodeMap;
athos@661:       const ResGraph& res_graph;
athos@610:       //      const EdgeIntMap& rev;
athos@661:       const CostMap &ol;
athos@610:       const NodeMap &pot;
athos@610:     public :
athos@661:       typedef typename CostMap::KeyType KeyType;
athos@661:       typedef typename CostMap::ValueType ValueType;
athos@610: 	
athos@661:       ValueType operator[](typename ResGraph::Edge e) const {     
athos@659: 	if (res_graph.forward(e))
athos@659: 	  return  ol[e]-(pot[res_graph.head(e)]-pot[res_graph.tail(e)]);   
athos@610: 	else
athos@659: 	  return -ol[e]-(pot[res_graph.head(e)]-pot[res_graph.tail(e)]);   
athos@610:       }     
athos@610: 	
athos@661:       ModCostMap(const ResGraph& _res_graph,
athos@661: 		   const CostMap &o,  const NodeMap &p) : 
athos@659: 	res_graph(_res_graph), /*rev(_rev),*/ ol(o), pot(p){}; 
athos@661:     };//ModCostMap
athos@610: 
athos@610: 
athos@610:   protected:
athos@610:     
athos@610:     //Input
athos@659:     const Graph& graph;
athos@661:     const CostMap& cost;
athos@635:     const SupplyDemandMap& supply_demand;//supply or demand of nodes
athos@610: 
athos@610: 
athos@610:     //auxiliary variables
athos@610: 
athos@610:     //To store the flow
athos@661:     FlowMap flow; 
athos@662:     //To store the potential (dual variables)
athos@662:     typedef typename Graph::template NodeMap<Cost> PotentialMap;
athos@662:     PotentialMap potential;
athos@610:     
athos@610: 
athos@661:     Cost total_cost;
athos@610: 
athos@610: 
athos@610:   public :
athos@610: 
athos@610: 
athos@662:    MinCostFlow(Graph& _graph, CostMap& _cost, SupplyDemandMap& _supply_demand):
athos@662:      graph(_graph), 
athos@662:      cost(_cost), 
athos@662:      supply_demand(_supply_demand), 
athos@662:      flow(_graph), 
athos@672:      potential(_graph){ }
athos@610: 
athos@610:     
athos@610:     ///Runs the algorithm.
athos@610: 
athos@610:     ///Runs the algorithm.
athos@635: 
athos@610:     ///\todo May be it does make sense to be able to start with a nonzero 
athos@610:     /// feasible primal-dual solution pair as well.
athos@659:     void run() {
athos@610: 
athos@672:       //To store excess-deficit values
athos@672:       SupplyDemandMap excess_deficit(graph);
athos@672: 
athos@610:       //Resetting variables from previous runs
athos@661:       //total_cost = 0;
athos@635: 
athos@672: 
athos@635:       typedef typename Graph::template NodeMap<int> HeapMap;
athos@662:       typedef BinHeap< Node, SupplyDemand, typename Graph::template NodeMap<int>,
athos@635: 	std::greater<SupplyDemand> > 	HeapType;
athos@635: 
athos@635:       //A heap for the excess nodes
athos@659:       HeapMap excess_nodes_map(graph,-1);
athos@635:       HeapType excess_nodes(excess_nodes_map);
athos@635: 
athos@635:       //A heap for the deficit nodes
athos@659:       HeapMap deficit_nodes_map(graph,-1);
athos@635:       HeapType deficit_nodes(deficit_nodes_map);
athos@635: 
athos@657:       //A container to store nonabundant arcs
athos@662:       std::list<Edge> nonabundant_arcs;
athos@659: 
athos@659: 	
athos@659:       FOR_EACH_LOC(typename Graph::EdgeIt, e, graph){
athos@610: 	flow.set(e,0);
athos@657: 	nonabundant_arcs.push_back(e);
athos@610:       }
athos@633: 
athos@633:       //Initial value for delta
athos@635:       SupplyDemand delta = 0;
athos@635: 
athos@657:       typedef UnionFindEnum<Node, Graph::template NodeMap> UFE;
athos@657: 
athos@657:       //A union-find structure to store the abundant components
athos@662:       typename UFE::MapType abund_comp_map(graph);
athos@657:       UFE abundant_components(abund_comp_map);
athos@657: 
athos@657: 
athos@657: 
athos@659:       FOR_EACH_LOC(typename Graph::NodeIt, n, graph){
athos@635:        	excess_deficit.set(n,supply_demand[n]);
athos@635: 	//A supply node
athos@635: 	if (excess_deficit[n] > 0){
athos@635: 	  excess_nodes.push(n,excess_deficit[n]);
athos@633: 	}
athos@635: 	//A demand node
athos@635: 	if (excess_deficit[n] < 0){
athos@635: 	  deficit_nodes.push(n, - excess_deficit[n]);
athos@635: 	}
athos@635: 	//Finding out starting value of delta
athos@635: 	if (delta < abs(excess_deficit[n])){
athos@635: 	  delta = abs(excess_deficit[n]);
athos@635: 	}
athos@633: 	//Initialize the copy of the Dijkstra potential to zero
athos@610: 	potential.set(n,0);
athos@657: 	//Every single point is an abundant component initially 
athos@657: 	abundant_components.insert(n);
athos@610:       }
athos@610: 
athos@635:       //It'll be allright as an initial value, though this value 
athos@635:       //can be the maximum deficit here
athos@635:       SupplyDemand max_excess = delta;
athos@610:       
athos@661:       ///\bug This is a serious cheat here, before we have an uncapacitated ResGraph
athos@662:       ConstEdgeMap const_inf_map(MAXINT);
athos@661:       
athos@633:       //We need a residual graph which is uncapacitated
athos@661:       ResGraph res_graph(graph, const_inf_map, flow);
athos@659:       
athos@659:       //An EdgeMap to tell which arcs are abundant
athos@662:       typename Graph::template EdgeMap<bool> abundant_arcs(graph);
athos@610: 
athos@659:       //Let's construct the sugraph consisting only of the abundant edges
athos@659:       typedef ConstMap< typename Graph::Node, bool > ConstNodeMap;
athos@672: 
athos@659:       ConstNodeMap const_true_map(true);
athos@662:       typedef SubGraphWrapper< const Graph, ConstNodeMap, 
athos@662: 	 typename Graph::template EdgeMap<bool> > 
athos@659: 	AbundantGraph;
athos@659:       AbundantGraph abundant_graph(graph, const_true_map, abundant_arcs );
athos@659:       
athos@659:       //Let's construct the residual graph for the abundant graph
athos@662:       typedef ResGraphWrapper<const AbundantGraph,int,ConstEdgeMap,FlowMap> 
athos@659: 	ResAbGraph;
athos@659:       //Again uncapacitated
athos@661:       ResAbGraph res_ab_graph(abundant_graph, const_inf_map, flow);
athos@659:       
athos@659:       //We need things for the bfs
athos@662:       typename ResAbGraph::template NodeMap<bool> bfs_reached(res_ab_graph);
athos@662:       typename ResAbGraph::template NodeMap<typename ResAbGraph::Edge> 
athos@659: 	bfs_pred(res_ab_graph); 
athos@662:       NullMap<typename ResAbGraph::Node, int> bfs_dist_dummy;
athos@671:       //Teszt celbol:
athos@671:       //BfsIterator<ResAbGraph, typename ResAbGraph::template NodeMap<bool> > 
athos@671:       //izebize(res_ab_graph, bfs_reached);
athos@659:       //We want to run bfs-es (more) on this graph 'res_ab_graph'
athos@671:       Bfs < const ResAbGraph , 
athos@662: 	typename ResAbGraph::template NodeMap<bool>, 
athos@662: 	typename ResAbGraph::template NodeMap<typename ResAbGraph::Edge>,
athos@659: 	NullMap<typename ResAbGraph::Node, int> > 
athos@659: 	bfs(res_ab_graph, bfs_reached, bfs_pred, bfs_dist_dummy);
athos@662:       /*This is what Marci wants for a bfs
athos@662: 	template <typename Graph, 
athos@662: 	    typename ReachedMap=typename Graph::template NodeMap<bool>, 
athos@662: 	    typename PredMap
athos@662: 	    =typename Graph::template NodeMap<typename Graph::Edge>, 
athos@662: 	    typename DistMap=typename Graph::template NodeMap<int> > 
athos@662: 	    class Bfs : public BfsIterator<Graph, ReachedMap> {
athos@662: 
athos@662:        */
athos@610:       
athos@661:       ModCostMap mod_cost(res_graph, cost, potential);
athos@610: 
athos@661:       Dijkstra<ResGraph, ModCostMap> dijkstra(res_graph, mod_cost);
athos@610: 
athos@671:       //We will use the number of the nodes of the graph often
athos@671:       int number_of_nodes = graph.nodeNum();
athos@633: 
athos@635:       while (max_excess > 0){
athos@635: 
athos@657: 	//Reset delta if still too big
athos@657: 	if (8*number_of_nodes*max_excess <= delta){
athos@657: 	  delta = max_excess;
athos@657: 	  
athos@657: 	}
athos@657: 
athos@645: 	/*
athos@645: 	 * Beginning of the delta scaling phase 
athos@645: 	*/
athos@635: 	//Merge and stuff
athos@657: 	{
athos@657: 	  SupplyDemand buf=8*number_of_nodes*delta;
athos@662: 	  typename std::list<Edge>::iterator i = nonabundant_arcs.begin();
athos@657: 	  while ( i != nonabundant_arcs.end() ){
athos@671: 	    if (flow[*i]>=buf){
athos@671: 	      Node a = abundant_components.find(res_graph.head(*i));
athos@671: 	      Node b = abundant_components.find(res_graph.tail(*i));
athos@657: 	      //Merge
athos@657: 	      if (a != b){
athos@657: 		abundant_components.join(a,b);
athos@659: 		//We want to push the smaller
athos@659: 		//Which has greater absolut value excess/deficit
athos@659: 		Node root=(abs(excess_deficit[a])>abs(excess_deficit[b]))?a:b;
athos@659: 		//Which is the other
athos@659: 		Node non_root = ( a == root ) ? b : a ;
athos@659: 		abundant_components.makeRep(root);
athos@659: 		SupplyDemand qty_to_augment = abs(excess_deficit[non_root]); 
athos@659: 		//Push the positive value
athos@659: 		if (excess_deficit[non_root] < 0)
athos@659: 		  swap(root, non_root);
athos@659: 		//If the non_root node has excess/deficit at all
athos@659: 		if (qty_to_augment>0){
athos@659: 		  //Find path and augment
athos@671: 		  bfs.run(typename AbundantGraph::Node(non_root));
athos@659: 		  //root should be reached
athos@659: 		  
athos@659: 		  //Augmenting on the found path
athos@659: 		  Node n=root;
athos@659: 		  ResGraphEdge e;
athos@659: 		  while (n!=non_root){
athos@671: 		    e = bfs_pred[n];
athos@659: 		    n = res_graph.tail(e);
athos@659: 		    res_graph.augment(e,qty_to_augment);
athos@659: 		  }
athos@659: 	  
athos@659: 		  //We know that non_root had positive excess
athos@671: 		  excess_nodes.set(non_root,
athos@671: 				   excess_nodes[non_root] - qty_to_augment);
athos@659: 		  //But what about root node
athos@659: 		  //It might have been positive and so became larger
athos@659: 		  if (excess_deficit[root]>0){
athos@671: 		    excess_nodes.set(root, 
athos@671: 				     excess_nodes[root] + qty_to_augment);
athos@659: 		  }
athos@659: 		  else{
athos@659: 		    //Or negative but not turned into positive
athos@671: 		    deficit_nodes.set(root, 
athos@671: 				      deficit_nodes[root] - qty_to_augment);
athos@659: 		  }
athos@659: 
athos@659: 		  //Update the excess_deficit map
athos@659: 		  excess_deficit[non_root] -= qty_to_augment;
athos@659: 		  excess_deficit[root] += qty_to_augment;
athos@659: 
athos@659: 		  
athos@659: 		}
athos@657: 	      }
athos@657: 	      //What happens to i?
athos@659: 	      //Marci and Zsolt says I shouldn't do such things
athos@659: 	      nonabundant_arcs.erase(i++);
athos@671: 	      abundant_arcs[*i] = true;
athos@657: 	    }
athos@657: 	    else
athos@657: 	      ++i;
athos@657: 	  }
athos@657: 	}
athos@657: 
athos@635: 
athos@635: 	Node s = excess_nodes.top(); 
athos@672: 	max_excess = excess_nodes[s];
athos@635: 	Node t = deficit_nodes.top(); 
athos@659: 	if (max_excess < deficit_nodes[t]){
athos@659: 	  max_excess = deficit_nodes[t];
athos@635: 	}
athos@635: 
athos@635: 
athos@662: 	while(max_excess > (number_of_nodes-1)*delta/number_of_nodes){
athos@659: 	  
athos@635: 	  
athos@635: 	  //s es t valasztasa
athos@659: 	  
athos@635: 	  //Dijkstra part	
athos@635: 	  dijkstra.run(s);
athos@659: 	  
athos@635: 	  /*We know from theory that t can be reached
athos@635: 	  if (!dijkstra.reached(t)){
athos@635: 	    //There are no k paths from s to t
athos@635: 	    break;
athos@635: 	  };
athos@635: 	  */
athos@635: 	  
athos@635: 	  //We have to change the potential
athos@661: 	  FOR_EACH_LOC(typename ResGraph::NodeIt, n, res_graph){
athos@635: 	    potential[n] += dijkstra.distMap()[n];
athos@635: 	  }
athos@635: 
athos@635: 
athos@635: 	  //Augmenting on the sortest path
athos@635: 	  Node n=t;
athos@635: 	  ResGraphEdge e;
athos@635: 	  while (n!=s){
athos@635: 	    e = dijkstra.pred(n);
athos@635: 	    n = dijkstra.predNode(n);
athos@635: 	    res_graph.augment(e,delta);
athos@635: 	    /*
athos@661: 	    //Let's update the total cost
athos@635: 	    if (res_graph.forward(e))
athos@661: 	      total_cost += cost[e];
athos@635: 	    else 
athos@661: 	      total_cost -= cost[e];	    
athos@635: 	    */
athos@635: 	  }
athos@659: 	  
athos@659: 	  //Update the excess_deficit map
athos@659: 	  excess_deficit[s] -= delta;
athos@659: 	  excess_deficit[t] += delta;
athos@659: 	  
athos@635: 
athos@635: 	  //Update the excess_nodes heap
athos@672: 	  if (delta > excess_nodes[s]){
athos@635: 	    if (delta > excess_nodes[s])
athos@635: 	      deficit_nodes.push(s,delta - excess_nodes[s]);
athos@635: 	    excess_nodes.pop();
athos@635: 	    
athos@635: 	  } 
athos@635: 	  else{
athos@671: 	    excess_nodes.set(s, excess_nodes[s] - delta);
athos@635: 	  }
athos@635: 	  //Update the deficit_nodes heap
athos@672: 	  if (delta > deficit_nodes[t]){
athos@635: 	    if (delta > deficit_nodes[t])
athos@635: 	      excess_nodes.push(t,delta - deficit_nodes[t]);
athos@635: 	    deficit_nodes.pop();
athos@635: 	    
athos@635: 	  } 
athos@635: 	  else{
athos@671: 	    deficit_nodes.set(t, deficit_nodes[t] - delta);
athos@635: 	  }
athos@635: 	  //Dijkstra part ends here
athos@659: 	  
athos@659: 	  //Choose s and t again
athos@659: 	  s = excess_nodes.top(); 
athos@659: 	  max_excess = excess_nodes[s];
athos@659: 	  t = deficit_nodes.top(); 
athos@659: 	  if (max_excess < deficit_nodes[t]){
athos@659: 	    max_excess = deficit_nodes[t];
athos@659: 	  }
athos@659: 
athos@633: 	}
athos@633: 
athos@633: 	/*
athos@635: 	 * End of the delta scaling phase 
athos@635: 	*/
athos@633: 
athos@635: 	//Whatever this means
athos@635: 	delta = delta / 2;
athos@635: 
athos@635: 	/*This is not necessary here
athos@635: 	//Update the max_excess
athos@635: 	max_excess = 0;
athos@659: 	FOR_EACH_LOC(typename Graph::NodeIt, n, graph){
athos@635: 	  if (max_excess < excess_deficit[n]){
athos@635: 	    max_excess = excess_deficit[n];
athos@610: 	  }
athos@610: 	}
athos@633: 	*/
athos@657: 
athos@610: 	  
athos@635:       }//while(max_excess > 0)
athos@610:       
athos@610: 
athos@671:       //return i;
athos@610:     }
athos@610: 
athos@610: 
athos@610: 
athos@610: 
athos@661:     ///This function gives back the total cost of the found paths.
athos@610:     ///Assumes that \c run() has been run and nothing changed since then.
athos@661:     Cost totalCost(){
athos@661:       return total_cost;
athos@610:     }
athos@610: 
athos@610:     ///Returns a const reference to the EdgeMap \c flow. \pre \ref run() must
athos@610:     ///be called before using this function.
athos@662:     const FlowMap &getFlow() const { return flow;}
athos@610: 
athos@610:   ///Returns a const reference to the NodeMap \c potential (the dual solution).
athos@610:     /// \pre \ref run() must be called before using this function.
athos@662:     const PotentialMap &getPotential() const { return potential;}
athos@610: 
athos@610:     ///This function checks, whether the given solution is optimal
athos@610:     ///Running after a \c run() should return with true
athos@672:     ///In this "state of the art" this only checks optimality, doesn't bother with feasibility
athos@610:     ///
athos@610:     ///\todo Is this OK here?
athos@610:     bool checkComplementarySlackness(){
athos@661:       Cost mod_pot;
athos@661:       Cost fl_e;
athos@659:       FOR_EACH_LOC(typename Graph::EdgeIt, e, graph){
athos@610: 	//C^{\Pi}_{i,j}
athos@661: 	mod_pot = cost[e]-potential[graph.head(e)]+potential[graph.tail(e)];
athos@610: 	fl_e = flow[e];
athos@610: 	//	std::cout << fl_e << std::endl;
athos@672: 	if (mod_pot > 0 && fl_e != 0)
athos@672: 	  return false;
athos@672: 
athos@610:       }
athos@610:       return true;
athos@610:     }
athos@672: 
athos@672:     /*
athos@672:     //For testing purposes only
athos@672:     //Lists the node_properties
athos@672:     void write_property_vector(const SupplyDemandMap& a,
athos@672: 			       char* prop_name="property"){
athos@672:       FOR_EACH_LOC(typename Graph::NodeIt, i, graph){
athos@672: 	cout<<"Node id.: "<<graph.id(i)<<", "<<prop_name<<" value: "<<a[i]<<endl;
athos@672:       }
athos@672:       cout<<endl;
athos@672:     }
athos@672:     */
athos@672:     bool checkFeasibility(){
athos@672:       SupplyDemandMap supdem(graph);
athos@672:       FOR_EACH_LOC(typename Graph::EdgeIt, e, graph){
athos@672: 
athos@672: 	if ( flow[e] < 0){
athos@672: 
athos@672: 	  return false;
athos@672: 	}
athos@672: 	supdem[graph.tail(e)] += flow[e];
athos@672: 	supdem[graph.head(e)] -= flow[e];
athos@672:       }
athos@672:       //write_property_vector(supdem, "supdem");
athos@672:       //write_property_vector(supply_demand, "supply_demand");
athos@672: 
athos@672:       FOR_EACH_LOC(typename Graph::NodeIt, n, graph){
athos@672: 
athos@672: 	if ( supdem[n] != supply_demand[n]){
athos@672: 	  //cout<<"Node id.: "<<graph.id(n)<<" : "<<supdem[n]<<", should be: "<<supply_demand[n]<<endl;
athos@672: 	  return false;
athos@672: 	}
athos@672:       }
athos@672: 
athos@672:       return true;
athos@672:     }
athos@672: 
athos@672:     bool checkOptimality(){
athos@672:       return checkFeasibility() && checkComplementarySlackness();
athos@672:     }
athos@610: 
athos@633:   }; //class MinCostFlow
athos@610: 
athos@610:   ///@}
athos@610: 
alpar@921: } //namespace lemon
athos@610: 
alpar@921: #endif //LEMON_MINCOSTFLOW_H