src/work/athos/mincostflows.h
author jacint
Tue, 04 May 2004 16:16:49 +0000
changeset 528 c00f6ebbe1e6
parent 523 4da6fb104664
child 530 d9c06ac0b3a3
permissions -rw-r--r--
Able to read min cost flow, max flow, shortest path, matching testgraphs
     1 // -*- c++ -*-
     2 #ifndef HUGO_MINCOSTFLOWS_H
     3 #define HUGO_MINCOSTFLOWS_H
     4 
     5 ///\ingroup galgs
     6 ///\file
     7 ///\brief An algorithm for finding a flow of value \c k (for small values of \c k) having minimal total cost 
     8 
     9 #include <iostream>
    10 #include <dijkstra.h>
    11 #include <graph_wrapper.h>
    12 #include <maps.h>
    13 #include <vector.h>
    14 
    15 
    16 namespace hugo {
    17 
    18 /// \addtogroup galgs
    19 /// @{
    20 
    21   ///\brief Implementation of an algorithm for finding a flow of value \c k 
    22   ///(for small values of \c k) having minimal total cost between 2 nodes 
    23   /// 
    24   ///
    25   /// The class \ref hugo::MinCostFlows "MinCostFlows" implements
    26   /// an algorithm for finding a flow of value \c k 
    27   ///(for small values of \c k) having minimal total cost  
    28   /// from a given source node to a given target node in an
    29   /// edge-weighted directed graph having nonnegative integer capacities.
    30   /// The range of the length (weight) function is nonnegative reals but 
    31   /// the range of capacity function is the set of nonnegative integers. 
    32   /// It is not a polinomial time algorithm for counting the minimum cost
    33   /// maximal flow, since it counts the minimum cost flow for every value 0..M
    34   /// where \c M is the value of the maximal flow.
    35   ///
    36   ///\author Attila Bernath
    37   template <typename Graph, typename LengthMap>
    38   class MinCostFlows {
    39 
    40     typedef typename LengthMap::ValueType Length;
    41 
    42     typedef typename LengthMap::ValueType Length;
    43     
    44     typedef typename Graph::Node Node;
    45     typedef typename Graph::NodeIt NodeIt;
    46     typedef typename Graph::Edge Edge;
    47     typedef typename Graph::OutEdgeIt OutEdgeIt;
    48     typedef typename Graph::template EdgeMap<int> EdgeIntMap;
    49 
    50     //    typedef ConstMap<Edge,int> ConstMap;
    51 
    52     typedef ResGraphWrapper<const Graph,int,EdgeIntMap,EdgeIntMap> ResGraphType;
    53 
    54     class ModLengthMap {   
    55       typedef typename ResGraphType::template NodeMap<Length> NodeMap;
    56       const ResGraphType& G;
    57       //      const EdgeIntMap& rev;
    58       const LengthMap &ol;
    59       const NodeMap &pot;
    60     public :
    61       typedef typename LengthMap::KeyType KeyType;
    62       typedef typename LengthMap::ValueType ValueType;
    63 	
    64       ValueType operator[](typename ResGraphType::Edge e) const {     
    65 	if (G.forward(e))
    66 	  return  ol[e]-(pot[G.head(e)]-pot[G.tail(e)]);   
    67 	else
    68 	  return -ol[e]-(pot[G.head(e)]-pot[G.tail(e)]);   
    69       }     
    70 	
    71       ModLengthMap(const ResGraphType& _G, const EdgeIntMap& _rev, 
    72 		   const LengthMap &o,  const NodeMap &p) : 
    73 	G(_G), /*rev(_rev),*/ ol(o), pot(p){}; 
    74     };//ModLengthMap
    75 
    76 
    77     
    78     //Input
    79     const Graph& G;
    80     const LengthMap& length;
    81     const EdgeIntMap& capacity;
    82 
    83     //auxiliary variables
    84 
    85     //The value is 1 iff the edge is reversed. 
    86     //If the algorithm has finished, the edges of the seeked paths are 
    87     //exactly those that are reversed 
    88     EdgeIntMap flow; 
    89     
    90     //Container to store found paths
    91     std::vector< std::vector<Edge> > paths;
    92     //typedef DirPath<Graph> DPath;
    93     //DPath paths;
    94 
    95 
    96     Length total_length;
    97 
    98   public :
    99 
   100 
   101     MinLengthPaths(Graph& _G, LengthMap& _length, EdgeIntMap& _cap) : G(_G), 
   102       length(_length), capacity(_cap), flow(_G)/*, dijkstra_dist(_G)*/{ }
   103 
   104     
   105     ///Runs the algorithm.
   106 
   107     ///Runs the algorithm.
   108     ///Returns k if there are at least k edge-disjoint paths from s to t.
   109     ///Otherwise it returns the number of found edge-disjoint paths from s to t.
   110     int run(Node s, Node t, int k) {
   111 
   112 
   113       //We need a residual graph
   114       ResGraphType res_graph(G, capacity, flow);
   115 
   116       //Initialize the copy of the Dijkstra potential to zero
   117       typename ResGraphType::template NodeMap<Length> dijkstra_dist(res_graph);
   118       ModLengthMap mod_length(res_graph, length, dijkstra_dist);
   119 
   120       Dijkstra<ResGraphType, ModLengthMap> dijkstra(res_graph, mod_length);
   121 
   122       int i;
   123       for (i=0; i<k; ++i){
   124 	dijkstra.run(s);
   125 	if (!dijkstra.reached(t)){
   126 	  //There are no k paths from s to t
   127 	  break;
   128 	};
   129 	
   130 	{
   131 	  //We have to copy the potential
   132 	  typename ResGraphType::NodeIt n;
   133 	  for ( res_graph.first(n) ; res_graph.valid(n) ; res_graph.next(n) ) {
   134 	      dijkstra_dist[n] += dijkstra.distMap()[n];
   135 	  }
   136 	}
   137 
   138 
   139 	//Augmenting on the sortest path
   140 	Node n=t;
   141 	Edge e;
   142 	while (n!=s){
   143 	  e = dijkstra.pred(n);
   144 	  n = dijkstra.predNode(n);
   145 	  G.augment(e,1);
   146 	}
   147 
   148 	  
   149       }
   150       
   151       /*
   152 	///\TODO To be implemented later
   153 
   154       //Let's find the paths
   155       //We put the paths into stl vectors (as an inner representation). 
   156       //In the meantime we lose the information stored in 'reversed'.
   157       //We suppose the lengths to be positive now.
   158 
   159       //Meanwhile we put the total length of the found paths 
   160       //in the member variable total_length
   161       paths.clear();
   162       total_length=0;
   163       paths.resize(k);
   164       for (int j=0; j<i; ++j){
   165 	Node n=s;
   166 	OutEdgeIt e;
   167 
   168 	while (n!=t){
   169 
   170 
   171 	  G.first(e,n);
   172 	  
   173 	  while (!reversed[e]){
   174 	    G.next(e);
   175 	  }
   176 	  n = G.head(e);
   177 	  paths[j].push_back(e);
   178 	  total_length += length[e];
   179 	  reversed[e] = 1-reversed[e];
   180 	}
   181 	
   182       }
   183       */
   184 
   185       return i;
   186     }
   187 
   188     ///This function gives back the total length of the found paths.
   189     ///Assumes that \c run() has been run and nothing changed since then.
   190     Length totalLength(){
   191       return total_length;
   192     }
   193 
   194     ///This function gives back the \c j-th path in argument p.
   195     ///Assumes that \c run() has been run and nothing changed since then.
   196     /// \warning It is assumed that \c p is constructed to be a path of graph \c G. If \c j is greater than the result of previous \c run, then the result here will be an empty path.
   197     template<typename DirPath>
   198     void getPath(DirPath& p, int j){
   199       p.clear();
   200       typename DirPath::Builder B(p);
   201       for(typename std::vector<Edge>::iterator i=paths[j].begin(); 
   202 	  i!=paths[j].end(); ++i ){
   203 	B.pushBack(*i);
   204       }
   205 
   206       B.commit();
   207     }
   208 
   209   }; //class MinLengthPaths
   210 
   211   ///@}
   212 
   213 } //namespace hugo
   214 
   215 #endif //HUGO_MINCOSTFLOW_H