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