src/hugo/mincostflows.h
author deba
Wed, 08 Sep 2004 12:06:45 +0000
changeset 822 88226d9fe821
parent 785 a9b0863c2265
child 860 3577b3db6089
permissions -rw-r--r--
The MapFactories have been removed from the code because
if we use macros then they increases only the complexity.

The pair iterators of the maps are separeted from the maps.

Some macros and comments has been changed.
     1 // -*- c++ -*-
     2 #ifndef HUGO_MINCOSTFLOWS_H
     3 #define HUGO_MINCOSTFLOWS_H
     4 
     5 ///\ingroup flowalgs
     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 
    10 #include <hugo/dijkstra.h>
    11 #include <hugo/graph_wrapper.h>
    12 #include <hugo/maps.h>
    13 #include <vector>
    14 
    15 namespace hugo {
    16 
    17 /// \addtogroup flowalgs
    18 /// @{
    19 
    20   ///\brief Implementation of an algorithm for finding a flow of value \c k 
    21   ///(for small values of \c k) having minimal total cost between 2 nodes 
    22   /// 
    23   ///
    24   /// The class \ref hugo::MinCostFlows "MinCostFlows" implements
    25   /// an algorithm for finding a flow of value \c k 
    26   ///(for small values of \c k) having minimal total cost  
    27   /// from a given source node to a given target node in an
    28   /// edge-weighted directed graph having nonnegative integer capacities.
    29   /// The range of the length (weight) function is nonnegative reals but 
    30   /// the range of capacity function is the set of nonnegative integers. 
    31   /// It is not a polinomial time algorithm for counting the minimum cost
    32   /// maximal flow, since it counts the minimum cost flow for every value 0..M
    33   /// where \c M is the value of the maximal flow.
    34   ///
    35   ///\author Attila Bernath
    36   template <typename Graph, typename LengthMap, typename CapacityMap>
    37   class MinCostFlows {
    38 
    39     typedef typename LengthMap::ValueType Length;
    40 
    41     //Warning: this should be integer type
    42     typedef typename CapacityMap::ValueType Capacity;
    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,CapacityMap,EdgeIntMap> ResGraphType;
    53     typedef typename ResGraphType::Edge ResGraphEdge;
    54 
    55     class ModLengthMap {   
    56       //typedef typename ResGraphType::template NodeMap<Length> NodeMap;
    57       typedef typename Graph::template NodeMap<Length> NodeMap;
    58       const ResGraphType& G;
    59       //      const EdgeIntMap& rev;
    60       const LengthMap &ol;
    61       const NodeMap &pot;
    62     public :
    63       typedef typename LengthMap::KeyType KeyType;
    64       typedef typename LengthMap::ValueType ValueType;
    65 	
    66       ValueType operator[](typename ResGraphType::Edge e) const {     
    67 	if (G.forward(e))
    68 	  return  ol[e]-(pot[G.head(e)]-pot[G.tail(e)]);   
    69 	else
    70 	  return -ol[e]-(pot[G.head(e)]-pot[G.tail(e)]);   
    71       }     
    72 	
    73       ModLengthMap(const ResGraphType& _G,
    74 		   const LengthMap &o,  const NodeMap &p) : 
    75 	G(_G), /*rev(_rev),*/ ol(o), pot(p){}; 
    76     };//ModLengthMap
    77 
    78 
    79   protected:
    80     
    81     //Input
    82     const Graph& G;
    83     const LengthMap& length;
    84     const CapacityMap& capacity;
    85 
    86 
    87     //auxiliary variables
    88 
    89     //To store the flow
    90     EdgeIntMap flow; 
    91     //To store the potential (dual variables)
    92     typedef typename Graph::template NodeMap<Length> PotentialMap;
    93     PotentialMap potential;
    94     
    95 
    96     Length total_length;
    97 
    98 
    99   public :
   100 
   101 
   102     MinCostFlows(Graph& _G, LengthMap& _length, CapacityMap& _cap) : G(_G), 
   103       length(_length), capacity(_cap), flow(_G), potential(_G){ }
   104 
   105     
   106     ///Runs the algorithm.
   107 
   108     ///Runs the algorithm.
   109     ///Returns k if there are at least k edge-disjoint paths from s to t.
   110     ///Otherwise it returns the number of found edge-disjoint paths from s to t.
   111     ///\todo May be it does make sense to be able to start with a nonzero 
   112     /// feasible primal-dual solution pair as well.
   113     int run(Node s, Node t, int k) {
   114 
   115       //Resetting variables from previous runs
   116       total_length = 0;
   117       
   118       for (typename Graph::EdgeIt e(G); e!=INVALID; ++e) flow.set(e, 0);
   119 
   120       //Initialize the potential to zero
   121       for (typename Graph::NodeIt n(G); n!=INVALID; ++n) potential.set(n, 0);
   122       
   123       
   124       //We need a residual graph
   125       ResGraphType res_graph(G, capacity, flow);
   126 
   127 
   128       ModLengthMap mod_length(res_graph, length, potential);
   129 
   130       Dijkstra<ResGraphType, ModLengthMap> dijkstra(res_graph, mod_length);
   131 
   132       int i;
   133       for (i=0; i<k; ++i){
   134 	dijkstra.run(s);
   135 	if (!dijkstra.reached(t)){
   136 	  //There are no k paths from s to t
   137 	  break;
   138 	};
   139 	
   140 	//We have to change the potential
   141         for(typename ResGraphType::NodeIt n(res_graph); n!=INVALID; ++n)
   142 	  potential[n] += dijkstra.distMap()[n];
   143 
   144 
   145 	//Augmenting on the sortest path
   146 	Node n=t;
   147 	ResGraphEdge e;
   148 	while (n!=s){
   149 	  e = dijkstra.pred(n);
   150 	  n = dijkstra.predNode(n);
   151 	  res_graph.augment(e,1);
   152 	  //Let's update the total length
   153 	  if (res_graph.forward(e))
   154 	    total_length += length[e];
   155 	  else 
   156 	    total_length -= length[e];	    
   157 	}
   158 
   159 	  
   160       }
   161       
   162 
   163       return i;
   164     }
   165 
   166 
   167 
   168 
   169     ///This function gives back the total length of the found paths.
   170     ///Assumes that \c run() has been run and nothing changed since then.
   171     Length totalLength(){
   172       return total_length;
   173     }
   174 
   175     ///Returns a const reference to the EdgeMap \c flow. \pre \ref run() must
   176     ///be called before using this function.
   177     const EdgeIntMap &getFlow() const { return flow;}
   178 
   179   ///Returns a const reference to the NodeMap \c potential (the dual solution).
   180     /// \pre \ref run() must be called before using this function.
   181     const PotentialMap &getPotential() const { return potential;}
   182 
   183     ///This function checks, whether the given solution is optimal
   184     ///Running after a \c run() should return with true
   185     ///In this "state of the art" this only check optimality, doesn't bother with feasibility
   186     ///
   187     ///\todo Is this OK here?
   188     bool checkComplementarySlackness(){
   189       Length mod_pot;
   190       Length fl_e;
   191         for(typename Graph::EdgeIt e(G); e!=INVALID; ++e) {
   192 	//C^{\Pi}_{i,j}
   193 	mod_pot = length[e]-potential[G.head(e)]+potential[G.tail(e)];
   194 	fl_e = flow[e];
   195 	//	std::cout << fl_e << std::endl;
   196 	if (0<fl_e && fl_e<capacity[e]){
   197 	  if (mod_pot != 0)
   198 	    return false;
   199 	}
   200 	else{
   201 	  if (mod_pot > 0 && fl_e != 0)
   202 	    return false;
   203 	  if (mod_pot < 0 && fl_e != capacity[e])
   204 	    return false;
   205 	}
   206       }
   207       return true;
   208     }
   209     
   210 
   211   }; //class MinCostFlows
   212 
   213   ///@}
   214 
   215 } //namespace hugo
   216 
   217 #endif //HUGO_MINCOSTFLOWS_H