|
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 /// having minimal total cost |
|
27 /// from a given source node to a given target node in an |
|
28 /// edge-weighted directed graph. To this end, |
|
29 /// the edge-capacities and edge-weitghs have to be nonnegative. |
|
30 /// The edge-capacities should be integers, but the edge-weights can be |
|
31 /// integers, reals or of other comparable numeric type. |
|
32 /// This algorithm is intended to use only for small values of \c k, |
|
33 /// since it is only polynomial in k, |
|
34 /// not in the length of k (which is log k). |
|
35 /// In order to find the minimum cost flow of value \c k it |
|
36 /// finds the minimum cost flow of value \c i for every |
|
37 /// \c i between 0 and \c k. |
|
38 /// |
|
39 ///\param Graph The directed graph type the algorithm runs on. |
|
40 ///\param LengthMap The type of the length map. |
|
41 ///\param CapacityMap The capacity map type. |
|
42 /// |
|
43 ///\author Attila Bernath |
|
44 template <typename Graph, typename LengthMap, typename CapacityMap> |
|
45 class MinCostFlows { |
|
46 |
|
47 typedef typename LengthMap::ValueType Length; |
|
48 |
|
49 //Warning: this should be integer type |
|
50 typedef typename CapacityMap::ValueType Capacity; |
|
51 |
|
52 typedef typename Graph::Node Node; |
|
53 typedef typename Graph::NodeIt NodeIt; |
|
54 typedef typename Graph::Edge Edge; |
|
55 typedef typename Graph::OutEdgeIt OutEdgeIt; |
|
56 typedef typename Graph::template EdgeMap<int> EdgeIntMap; |
|
57 |
|
58 |
|
59 typedef ResGraphWrapper<const Graph,int,CapacityMap,EdgeIntMap> ResGraphType; |
|
60 typedef typename ResGraphType::Edge ResGraphEdge; |
|
61 |
|
62 class ModLengthMap { |
|
63 typedef typename Graph::template NodeMap<Length> NodeMap; |
|
64 const ResGraphType& G; |
|
65 const LengthMap &ol; |
|
66 const NodeMap &pot; |
|
67 public : |
|
68 typedef typename LengthMap::KeyType KeyType; |
|
69 typedef typename LengthMap::ValueType ValueType; |
|
70 |
|
71 ValueType operator[](typename ResGraphType::Edge e) const { |
|
72 if (G.forward(e)) |
|
73 return ol[e]-(pot[G.head(e)]-pot[G.tail(e)]); |
|
74 else |
|
75 return -ol[e]-(pot[G.head(e)]-pot[G.tail(e)]); |
|
76 } |
|
77 |
|
78 ModLengthMap(const ResGraphType& _G, |
|
79 const LengthMap &o, const NodeMap &p) : |
|
80 G(_G), /*rev(_rev),*/ ol(o), pot(p){}; |
|
81 };//ModLengthMap |
|
82 |
|
83 |
|
84 protected: |
|
85 |
|
86 //Input |
|
87 const Graph& G; |
|
88 const LengthMap& length; |
|
89 const CapacityMap& capacity; |
|
90 |
|
91 |
|
92 //auxiliary variables |
|
93 |
|
94 //To store the flow |
|
95 EdgeIntMap flow; |
|
96 //To store the potential (dual variables) |
|
97 typedef typename Graph::template NodeMap<Length> PotentialMap; |
|
98 PotentialMap potential; |
|
99 |
|
100 |
|
101 Length total_length; |
|
102 |
|
103 |
|
104 public : |
|
105 |
|
106 /// The constructor of the class. |
|
107 |
|
108 ///\param _G The directed graph the algorithm runs on. |
|
109 ///\param _length The length (weight or cost) of the edges. |
|
110 ///\param _cap The capacity of the edges. |
|
111 MinCostFlows(Graph& _G, LengthMap& _length, CapacityMap& _cap) : G(_G), |
|
112 length(_length), capacity(_cap), flow(_G), potential(_G){ } |
|
113 |
|
114 |
|
115 ///Runs the algorithm. |
|
116 |
|
117 ///Runs the algorithm. |
|
118 ///Returns k if there is a flow of value at least k edge-disjoint |
|
119 ///from s to t. |
|
120 ///Otherwise it returns the maximum value of a flow from s to t. |
|
121 /// |
|
122 ///\param s The source node. |
|
123 ///\param t The target node. |
|
124 ///\param k The value of the flow we are looking for. |
|
125 /// |
|
126 ///\todo May be it does make sense to be able to start with a nonzero |
|
127 /// feasible primal-dual solution pair as well. |
|
128 int run(Node s, Node t, int k) { |
|
129 |
|
130 //Resetting variables from previous runs |
|
131 total_length = 0; |
|
132 |
|
133 for (typename Graph::EdgeIt e(G); e!=INVALID; ++e) flow.set(e, 0); |
|
134 |
|
135 //Initialize the potential to zero |
|
136 for (typename Graph::NodeIt n(G); n!=INVALID; ++n) potential.set(n, 0); |
|
137 |
|
138 |
|
139 //We need a residual graph |
|
140 ResGraphType res_graph(G, capacity, flow); |
|
141 |
|
142 |
|
143 ModLengthMap mod_length(res_graph, length, potential); |
|
144 |
|
145 Dijkstra<ResGraphType, ModLengthMap> dijkstra(res_graph, mod_length); |
|
146 |
|
147 int i; |
|
148 for (i=0; i<k; ++i){ |
|
149 dijkstra.run(s); |
|
150 if (!dijkstra.reached(t)){ |
|
151 //There are no flow of value k from s to t |
|
152 break; |
|
153 }; |
|
154 |
|
155 //We have to change the potential |
|
156 for(typename ResGraphType::NodeIt n(res_graph); n!=INVALID; ++n) |
|
157 potential[n] += dijkstra.distMap()[n]; |
|
158 |
|
159 |
|
160 //Augmenting on the sortest path |
|
161 Node n=t; |
|
162 ResGraphEdge e; |
|
163 while (n!=s){ |
|
164 e = dijkstra.pred(n); |
|
165 n = dijkstra.predNode(n); |
|
166 res_graph.augment(e,1); |
|
167 //Let's update the total length |
|
168 if (res_graph.forward(e)) |
|
169 total_length += length[e]; |
|
170 else |
|
171 total_length -= length[e]; |
|
172 } |
|
173 |
|
174 |
|
175 } |
|
176 |
|
177 |
|
178 return i; |
|
179 } |
|
180 |
|
181 |
|
182 |
|
183 /// Gives back the total weight of the found flow. |
|
184 |
|
185 ///This function gives back the total weight of the found flow. |
|
186 ///Assumes that \c run() has been run and nothing changed since then. |
|
187 Length totalLength(){ |
|
188 return total_length; |
|
189 } |
|
190 |
|
191 ///Returns a const reference to the EdgeMap \c flow. |
|
192 |
|
193 ///Returns a const reference to the EdgeMap \c flow. |
|
194 ///\pre \ref run() must |
|
195 ///be called before using this function. |
|
196 const EdgeIntMap &getFlow() const { return flow;} |
|
197 |
|
198 ///Returns a const reference to the NodeMap \c potential (the dual solution). |
|
199 |
|
200 ///Returns a const reference to the NodeMap \c potential (the dual solution). |
|
201 /// \pre \ref run() must be called before using this function. |
|
202 const PotentialMap &getPotential() const { return potential;} |
|
203 |
|
204 /// Checking the complementary slackness optimality criteria |
|
205 |
|
206 ///This function checks, whether the given solution is optimal |
|
207 ///If executed after the call of \c run() then it should return with true. |
|
208 ///This function only checks optimality, doesn't bother with feasibility. |
|
209 ///It is meant for testing purposes. |
|
210 /// |
|
211 bool checkComplementarySlackness(){ |
|
212 Length mod_pot; |
|
213 Length fl_e; |
|
214 for(typename Graph::EdgeIt e(G); e!=INVALID; ++e) { |
|
215 //C^{\Pi}_{i,j} |
|
216 mod_pot = length[e]-potential[G.head(e)]+potential[G.tail(e)]; |
|
217 fl_e = flow[e]; |
|
218 if (0<fl_e && fl_e<capacity[e]) { |
|
219 /// \todo better comparison is needed for real types, moreover, |
|
220 /// this comparison here is superfluous. |
|
221 if (mod_pot != 0) |
|
222 return false; |
|
223 } |
|
224 else { |
|
225 if (mod_pot > 0 && fl_e != 0) |
|
226 return false; |
|
227 if (mod_pot < 0 && fl_e != capacity[e]) |
|
228 return false; |
|
229 } |
|
230 } |
|
231 return true; |
|
232 } |
|
233 |
|
234 |
|
235 }; //class MinCostFlows |
|
236 |
|
237 ///@} |
|
238 |
|
239 } //namespace hugo |
|
240 |
|
241 #endif //HUGO_MINCOSTFLOWS_H |