| [276] | 1 | // -*- c++ -*- | 
|---|
| [523] | 2 | #ifndef HUGO_MINCOSTFLOWS_H | 
|---|
|  | 3 | #define HUGO_MINCOSTFLOWS_H | 
|---|
| [276] | 4 |  | 
|---|
| [491] | 5 | ///\ingroup galgs | 
|---|
| [294] | 6 | ///\file | 
|---|
| [523] | 7 | ///\brief An algorithm for finding a flow of value \c k (for small values of \c k) having minimal total cost | 
|---|
| [294] | 8 |  | 
|---|
| [276] | 9 | #include <iostream> | 
|---|
| [551] | 10 | #include <hugo/dijkstra.h> | 
|---|
| [276] | 11 | #include <graph_wrapper.h> | 
|---|
| [551] | 12 | #include <hugo/maps.h> | 
|---|
|  | 13 | #include <vector> | 
|---|
| [530] | 14 | #include <for_each_macros.h> | 
|---|
| [306] | 15 |  | 
|---|
| [276] | 16 | namespace hugo { | 
|---|
|  | 17 |  | 
|---|
| [430] | 18 | /// \addtogroup galgs | 
|---|
|  | 19 | /// @{ | 
|---|
| [322] | 20 |  | 
|---|
| [523] | 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 | /// | 
|---|
| [310] | 24 | /// | 
|---|
| [523] | 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 | 
|---|
| [310] | 28 | /// from a given source node to a given target node in an | 
|---|
| [523] | 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. | 
|---|
| [456] | 35 | /// | 
|---|
|  | 36 | ///\author Attila Bernath | 
|---|
| [530] | 37 | template <typename Graph, typename LengthMap, typename CapacityMap> | 
|---|
| [523] | 38 | class MinCostFlows { | 
|---|
| [276] | 39 |  | 
|---|
| [310] | 40 | typedef typename LengthMap::ValueType Length; | 
|---|
| [527] | 41 |  | 
|---|
| [530] | 42 | //Warning: this should be integer type | 
|---|
|  | 43 | typedef typename CapacityMap::ValueType Capacity; | 
|---|
| [511] | 44 |  | 
|---|
| [276] | 45 | typedef typename Graph::Node Node; | 
|---|
|  | 46 | typedef typename Graph::NodeIt NodeIt; | 
|---|
|  | 47 | typedef typename Graph::Edge Edge; | 
|---|
|  | 48 | typedef typename Graph::OutEdgeIt OutEdgeIt; | 
|---|
| [511] | 49 | typedef typename Graph::template EdgeMap<int> EdgeIntMap; | 
|---|
| [306] | 50 |  | 
|---|
| [527] | 51 | //    typedef ConstMap<Edge,int> ConstMap; | 
|---|
| [306] | 52 |  | 
|---|
| [530] | 53 | typedef ResGraphWrapper<const Graph,int,CapacityMap,EdgeIntMap> ResGraphType; | 
|---|
|  | 54 | typedef typename ResGraphType::Edge ResGraphEdge; | 
|---|
| [547] | 55 |  | 
|---|
| [306] | 56 | class ModLengthMap { | 
|---|
| [547] | 57 | //typedef typename ResGraphType::template NodeMap<Length> NodeMap; | 
|---|
|  | 58 | typedef typename Graph::template NodeMap<Length> NodeMap; | 
|---|
| [306] | 59 | const ResGraphType& G; | 
|---|
| [527] | 60 | //      const EdgeIntMap& rev; | 
|---|
| [310] | 61 | const LengthMap &ol; | 
|---|
|  | 62 | const NodeMap &pot; | 
|---|
| [306] | 63 | public : | 
|---|
|  | 64 | typedef typename LengthMap::KeyType KeyType; | 
|---|
|  | 65 | typedef typename LengthMap::ValueType ValueType; | 
|---|
| [511] | 66 |  | 
|---|
| [306] | 67 | ValueType operator[](typename ResGraphType::Edge e) const { | 
|---|
| [527] | 68 | if (G.forward(e)) | 
|---|
|  | 69 | return  ol[e]-(pot[G.head(e)]-pot[G.tail(e)]); | 
|---|
|  | 70 | else | 
|---|
|  | 71 | return -ol[e]-(pot[G.head(e)]-pot[G.tail(e)]); | 
|---|
| [306] | 72 | } | 
|---|
| [511] | 73 |  | 
|---|
| [530] | 74 | ModLengthMap(const ResGraphType& _G, | 
|---|
| [310] | 75 | const LengthMap &o,  const NodeMap &p) : | 
|---|
| [527] | 76 | G(_G), /*rev(_rev),*/ ol(o), pot(p){}; | 
|---|
| [511] | 77 | };//ModLengthMap | 
|---|
|  | 78 |  | 
|---|
|  | 79 |  | 
|---|
| [306] | 80 |  | 
|---|
| [527] | 81 | //Input | 
|---|
| [276] | 82 | const Graph& G; | 
|---|
|  | 83 | const LengthMap& length; | 
|---|
| [530] | 84 | const CapacityMap& capacity; | 
|---|
| [276] | 85 |  | 
|---|
| [328] | 86 | //auxiliary variables | 
|---|
| [322] | 87 |  | 
|---|
| [551] | 88 | //To store the flow | 
|---|
| [527] | 89 | EdgeIntMap flow; | 
|---|
| [551] | 90 | //To store the potentila (dual variables) | 
|---|
| [547] | 91 | typename Graph::template NodeMap<Length> potential; | 
|---|
| [276] | 92 |  | 
|---|
| [322] | 93 | //Container to store found paths | 
|---|
| [551] | 94 | //std::vector< std::vector<Edge> > paths; | 
|---|
| [511] | 95 | //typedef DirPath<Graph> DPath; | 
|---|
|  | 96 | //DPath paths; | 
|---|
|  | 97 |  | 
|---|
|  | 98 |  | 
|---|
|  | 99 | Length total_length; | 
|---|
| [322] | 100 |  | 
|---|
| [276] | 101 | public : | 
|---|
| [310] | 102 |  | 
|---|
| [276] | 103 |  | 
|---|
| [530] | 104 | MinCostFlows(Graph& _G, LengthMap& _length, CapacityMap& _cap) : G(_G), | 
|---|
| [547] | 105 | length(_length), capacity(_cap), flow(_G), potential(_G){ } | 
|---|
| [276] | 106 |  | 
|---|
| [294] | 107 |  | 
|---|
| [329] | 108 | ///Runs the algorithm. | 
|---|
|  | 109 |  | 
|---|
|  | 110 | ///Runs the algorithm. | 
|---|
| [306] | 111 | ///Returns k if there are at least k edge-disjoint paths from s to t. | 
|---|
| [329] | 112 | ///Otherwise it returns the number of found edge-disjoint paths from s to t. | 
|---|
| [306] | 113 | int run(Node s, Node t, int k) { | 
|---|
| [276] | 114 |  | 
|---|
| [530] | 115 | //Resetting variables from previous runs | 
|---|
|  | 116 | total_length = 0; | 
|---|
| [547] | 117 |  | 
|---|
| [530] | 118 | FOR_EACH_LOC(typename Graph::EdgeIt, e, G){ | 
|---|
|  | 119 | flow.set(e,0); | 
|---|
|  | 120 | } | 
|---|
| [547] | 121 |  | 
|---|
|  | 122 | FOR_EACH_LOC(typename Graph::NodeIt, n, G){ | 
|---|
|  | 123 | //cout << potential[n]<<endl; | 
|---|
|  | 124 | potential.set(n,0); | 
|---|
|  | 125 | } | 
|---|
|  | 126 |  | 
|---|
| [511] | 127 |  | 
|---|
| [530] | 128 |  | 
|---|
| [527] | 129 | //We need a residual graph | 
|---|
|  | 130 | ResGraphType res_graph(G, capacity, flow); | 
|---|
| [306] | 131 |  | 
|---|
|  | 132 | //Initialize the copy of the Dijkstra potential to zero | 
|---|
| [547] | 133 |  | 
|---|
|  | 134 | //typename ResGraphType::template NodeMap<Length> potential(res_graph); | 
|---|
|  | 135 |  | 
|---|
|  | 136 |  | 
|---|
|  | 137 | ModLengthMap mod_length(res_graph, length, potential); | 
|---|
| [306] | 138 |  | 
|---|
|  | 139 | Dijkstra<ResGraphType, ModLengthMap> dijkstra(res_graph, mod_length); | 
|---|
| [322] | 140 |  | 
|---|
|  | 141 | int i; | 
|---|
|  | 142 | for (i=0; i<k; ++i){ | 
|---|
| [276] | 143 | dijkstra.run(s); | 
|---|
|  | 144 | if (!dijkstra.reached(t)){ | 
|---|
| [314] | 145 | //There are no k paths from s to t | 
|---|
| [322] | 146 | break; | 
|---|
| [276] | 147 | }; | 
|---|
| [306] | 148 |  | 
|---|
|  | 149 | { | 
|---|
|  | 150 | //We have to copy the potential | 
|---|
|  | 151 | typename ResGraphType::NodeIt n; | 
|---|
|  | 152 | for ( res_graph.first(n) ; res_graph.valid(n) ; res_graph.next(n) ) { | 
|---|
| [547] | 153 | potential[n] += dijkstra.distMap()[n]; | 
|---|
| [306] | 154 | } | 
|---|
|  | 155 | } | 
|---|
|  | 156 |  | 
|---|
|  | 157 |  | 
|---|
| [527] | 158 | //Augmenting on the sortest path | 
|---|
| [276] | 159 | Node n=t; | 
|---|
| [530] | 160 | ResGraphEdge e; | 
|---|
| [276] | 161 | while (n!=s){ | 
|---|
| [291] | 162 | e = dijkstra.pred(n); | 
|---|
|  | 163 | n = dijkstra.predNode(n); | 
|---|
| [530] | 164 | res_graph.augment(e,1); | 
|---|
|  | 165 | //Let's update the total length | 
|---|
|  | 166 | if (res_graph.forward(e)) | 
|---|
|  | 167 | total_length += length[e]; | 
|---|
|  | 168 | else | 
|---|
|  | 169 | total_length -= length[e]; | 
|---|
| [276] | 170 | } | 
|---|
|  | 171 |  | 
|---|
|  | 172 |  | 
|---|
|  | 173 | } | 
|---|
| [322] | 174 |  | 
|---|
|  | 175 |  | 
|---|
|  | 176 | return i; | 
|---|
| [276] | 177 | } | 
|---|
|  | 178 |  | 
|---|
| [530] | 179 |  | 
|---|
|  | 180 |  | 
|---|
| [547] | 181 |  | 
|---|
| [511] | 182 | ///This function gives back the total length of the found paths. | 
|---|
|  | 183 | ///Assumes that \c run() has been run and nothing changed since then. | 
|---|
|  | 184 | Length totalLength(){ | 
|---|
|  | 185 | return total_length; | 
|---|
|  | 186 | } | 
|---|
|  | 187 |  | 
|---|
| [551] | 188 | //This function checks, whether the given solution is optimal | 
|---|
|  | 189 | //Running after a \c run() should return with true | 
|---|
| [554] | 190 | //In this "state of the art" this only check optimality, doesn't bother with feasibility | 
|---|
| [551] | 191 | bool checkSolution(){ | 
|---|
|  | 192 | Length mod_pot; | 
|---|
|  | 193 | Length fl_e; | 
|---|
|  | 194 | FOR_EACH_LOC(typename Graph::EdgeIt, e, G){ | 
|---|
|  | 195 | //C^{\Pi}_{i,j} | 
|---|
| [554] | 196 | mod_pot = length[e]-potential[G.head(e)]+potential[G.tail(e)]; | 
|---|
| [551] | 197 | fl_e = flow[e]; | 
|---|
| [554] | 198 | //      std::cout << fl_e << std::endl; | 
|---|
| [551] | 199 | if (0<fl_e && fl_e<capacity[e]){ | 
|---|
|  | 200 | if (mod_pot != 0) | 
|---|
|  | 201 | return false; | 
|---|
|  | 202 | } | 
|---|
|  | 203 | else{ | 
|---|
|  | 204 | if (mod_pot > 0 && fl_e != 0) | 
|---|
|  | 205 | return false; | 
|---|
|  | 206 | if (mod_pot < 0 && fl_e != capacity[e]) | 
|---|
|  | 207 | return false; | 
|---|
|  | 208 | } | 
|---|
|  | 209 | } | 
|---|
|  | 210 | return true; | 
|---|
|  | 211 | } | 
|---|
|  | 212 |  | 
|---|
| [530] | 213 | /* | 
|---|
|  | 214 | ///\todo To be implemented later | 
|---|
|  | 215 |  | 
|---|
| [511] | 216 | ///This function gives back the \c j-th path in argument p. | 
|---|
|  | 217 | ///Assumes that \c run() has been run and nothing changed since then. | 
|---|
| [519] | 218 | /// \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. | 
|---|
| [511] | 219 | template<typename DirPath> | 
|---|
|  | 220 | void getPath(DirPath& p, int j){ | 
|---|
|  | 221 | p.clear(); | 
|---|
|  | 222 | typename DirPath::Builder B(p); | 
|---|
|  | 223 | for(typename std::vector<Edge>::iterator i=paths[j].begin(); | 
|---|
|  | 224 | i!=paths[j].end(); ++i ){ | 
|---|
| [520] | 225 | B.pushBack(*i); | 
|---|
| [511] | 226 | } | 
|---|
|  | 227 |  | 
|---|
|  | 228 | B.commit(); | 
|---|
|  | 229 | } | 
|---|
| [276] | 230 |  | 
|---|
| [530] | 231 | */ | 
|---|
|  | 232 |  | 
|---|
|  | 233 | }; //class MinCostFlows | 
|---|
| [276] | 234 |  | 
|---|
| [430] | 235 | ///@} | 
|---|
| [276] | 236 |  | 
|---|
|  | 237 | } //namespace hugo | 
|---|
|  | 238 |  | 
|---|
| [527] | 239 | #endif //HUGO_MINCOSTFLOW_H | 
|---|