1 #ifndef FLOW_H_
2 #define FLOW_H_
3 
4 #include <Eigen/Core>
5 #include <list>
6 #include <map>
7 #include <vector>
8 
9 #include "config.hpp"
10 
11 #include <boost/graph/adjacency_list.hpp>
12 #include <boost/graph/boykov_kolmogorov_max_flow.hpp>
13 #include <boost/graph/edmonds_karp_max_flow.hpp>
14 #include <boost/graph/push_relabel_max_flow.hpp>
15 
16 #include <lemon/network_simplex.h>
17 #include <lemon/preflow.h>
18 #include <lemon/smart_graph.h>
19 
20 using namespace boost;
21 using namespace Eigen;
22 
23 namespace qflow {
24 
25 class MaxFlowHelper {
26    public:
MaxFlowHelper()27     MaxFlowHelper() {}
~MaxFlowHelper()28     virtual ~MaxFlowHelper(){};
29     virtual void resize(int n, int m) = 0;
30     virtual void addEdge(int x, int y, int c, int rc, int v, int cost = 1) = 0;
31     virtual int compute() = 0;
32     virtual void applyTo(std::vector<Vector2i>& edge_diff) = 0;
33 };
34 
35 class BoykovMaxFlowHelper : public MaxFlowHelper {
36    public:
37     typedef int EdgeWeightType;
38     typedef adjacency_list_traits<vecS, vecS, directedS> Traits;
39     // clang-format off
40     typedef adjacency_list < vecS, vecS, directedS,
41         property < vertex_name_t, std::string,
42         property < vertex_index_t, long,
43         property < vertex_color_t, boost::default_color_type,
44         property < vertex_distance_t, long,
45         property < vertex_predecessor_t, Traits::edge_descriptor > > > > >,
46 
47         property < edge_capacity_t, EdgeWeightType,
48         property < edge_residual_capacity_t, EdgeWeightType,
49         property < edge_reverse_t, Traits::edge_descriptor > > > > Graph;
50     // clang-format on
51 
52    public:
BoykovMaxFlowHelper()53     BoykovMaxFlowHelper() { rev = get(edge_reverse, g); }
resize(int n,int m)54     void resize(int n, int m) {
55         vertex_descriptors.resize(n);
56         for (int i = 0; i < n; ++i) vertex_descriptors[i] = add_vertex(g);
57     }
compute()58     int compute() {
59         EdgeWeightType flow =
60             boykov_kolmogorov_max_flow(g, vertex_descriptors.front(), vertex_descriptors.back());
61         return flow;
62     }
addDirectEdge(Traits::vertex_descriptor & v1,Traits::vertex_descriptor & v2,property_map<Graph,edge_reverse_t>::type & rev,const int capacity,const int inv_capacity,Graph & g,Traits::edge_descriptor & e1,Traits::edge_descriptor & e2)63     void addDirectEdge(Traits::vertex_descriptor& v1, Traits::vertex_descriptor& v2,
64                        property_map<Graph, edge_reverse_t>::type& rev, const int capacity,
65                        const int inv_capacity, Graph& g, Traits::edge_descriptor& e1,
66                        Traits::edge_descriptor& e2) {
67         e1 = add_edge(v1, v2, g).first;
68         e2 = add_edge(v2, v1, g).first;
69         put(edge_capacity, g, e1, capacity);
70         put(edge_capacity, g, e2, inv_capacity);
71 
72         rev[e1] = e2;
73         rev[e2] = e1;
74     }
addEdge(int x,int y,int c,int rc,int v,int cost=1)75     void addEdge(int x, int y, int c, int rc, int v, int cost = 1) {
76         Traits::edge_descriptor e1, e2;
77         addDirectEdge(vertex_descriptors[x], vertex_descriptors[y], rev, c, rc, g, e1, e2);
78         if (v != -1) {
79             edge_to_variables[e1] = std::make_pair(v, -1);
80             edge_to_variables[e2] = std::make_pair(v, 1);
81         }
82     }
applyTo(std::vector<Vector2i> & edge_diff)83     void applyTo(std::vector<Vector2i>& edge_diff) {
84         property_map<Graph, edge_capacity_t>::type capacity = get(edge_capacity, g);
85         property_map<Graph, edge_residual_capacity_t>::type residual_capacity =
86             get(edge_residual_capacity, g);
87 
88         graph_traits<Graph>::vertex_iterator u_iter, u_end;
89         graph_traits<Graph>::out_edge_iterator ei, e_end;
90         for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter)
91             for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei)
92                 if (capacity[*ei] > 0) {
93                     int flow = (capacity[*ei] - residual_capacity[*ei]);
94                     if (flow > 0) {
95                         auto it = edge_to_variables.find(*ei);
96                         if (it != edge_to_variables.end()) {
97                             edge_diff[it->second.first / 2][it->second.first % 2] +=
98                                 it->second.second * flow;
99                         }
100                     }
101                 }
102     }
103 
104    private:
105     Graph g;
106     property_map<Graph, edge_reverse_t>::type rev;
107     std::vector<Traits::vertex_descriptor> vertex_descriptors;
108     std::map<Traits::edge_descriptor, std::pair<int, int>> edge_to_variables;
109 };
110 
111 class NetworkSimplexFlowHelper : public MaxFlowHelper {
112    public:
113     using Weight = int;
114     using Capacity = int;
115     using Graph = lemon::SmartDigraph;
116     using Node = Graph::Node;
117     using Arc = Graph::Arc;
118     template <typename ValueType>
119     using ArcMap = lemon::SmartDigraph::ArcMap<ValueType>;
120     using Preflow = lemon::Preflow<lemon::SmartDigraph, ArcMap<Capacity>>;
121     using NetworkSimplex = lemon::NetworkSimplex<lemon::SmartDigraph, Capacity, Weight>;
122 
123    public:
NetworkSimplexFlowHelper()124     NetworkSimplexFlowHelper() : cost(graph), capacity(graph), flow(graph), variable(graph) {}
~NetworkSimplexFlowHelper()125     ~NetworkSimplexFlowHelper(){};
resize(int n,int m)126     void resize(int n, int m) {
127         nodes.reserve(n);
128         for (int i = 0; i < n; ++i) nodes.push_back(graph.addNode());
129     }
addEdge(int x,int y,int c,int rc,int v,int cst=1)130     void addEdge(int x, int y, int c, int rc, int v, int cst = 1) {
131         assert(x >= 0);
132         assert(v >= -1);
133         if (c) {
134             auto e1 = graph.addArc(nodes[x], nodes[y]);
135             cost[e1] = cst;
136             capacity[e1] = c;
137             variable[e1] = std::make_pair(v, 1);
138         }
139 
140         if (rc) {
141             auto e2 = graph.addArc(nodes[y], nodes[x]);
142             cost[e2] = cst;
143             capacity[e2] = rc;
144             variable[e2] = std::make_pair(v, -1);
145         }
146     }
compute()147     int compute() {
148         Preflow pf(graph, capacity, nodes.front(), nodes.back());
149         NetworkSimplex ns(graph);
150 
151         // Run preflow to find maximum flow
152         lprintf("push-relabel flow... ");
153         pf.runMinCut();
154         int maxflow = pf.flowValue();
155 
156         // Run network simplex to find minimum cost maximum flow
157         ns.costMap(cost).upperMap(capacity).stSupply(nodes.front(), nodes.back(), maxflow);
158         auto status = ns.run();
159         switch (status) {
160             case NetworkSimplex::OPTIMAL:
161                 ns.flowMap(flow);
162                 break;
163             case NetworkSimplex::INFEASIBLE:
164                 lputs("NetworkSimplex::INFEASIBLE");
165                 assert(0);
166                 break;
167             default:
168                 lputs("Unknown: NetworkSimplex::Default");
169                 assert(0);
170                 break;
171         }
172 
173         return maxflow;
174     }
applyTo(std::vector<Vector2i> & edge_diff)175     void applyTo(std::vector<Vector2i>& edge_diff) {
176         for (Graph::ArcIt e(graph); e != lemon::INVALID; ++e) {
177             int var = variable[e].first;
178             if (var == -1) continue;
179             int sgn = variable[e].second;
180             edge_diff[var / 2][var % 2] -= sgn * flow[e];
181         }
182     }
183 
184    private:
185     Graph graph;
186     ArcMap<Weight> cost;
187     ArcMap<Capacity> capacity;
188     ArcMap<Capacity> flow;
189     ArcMap<std::pair<int, int>> variable;
190     std::vector<Node> nodes;
191     std::vector<Arc> edges;
192 };
193 
194 #ifdef WITH_GUROBI
195 
196 #include <gurobi_c++.h>
197 
198 class GurobiFlowHelper : public MaxFlowHelper {
199    public:
GurobiFlowHelper()200     GurobiFlowHelper() {}
~GurobiFlowHelper()201     virtual ~GurobiFlowHelper(){};
resize(int n,int m)202     virtual void resize(int n, int m) {
203         nodes.resize(n * 2);
204         edges.resize(m);
205     }
addEdge(int x,int y,int c,int rc,int v,int cost=1)206     virtual void addEdge(int x, int y, int c, int rc, int v, int cost = 1) {
207         nodes[x * 2 + 0].push_back(vars.size());
208         nodes[y * 2 + 1].push_back(vars.size());
209         vars.push_back(model.addVar(0, c, 0, GRB_INTEGER));
210         edges.push_back(std::make_pair(v, 1));
211 
212         nodes[y * 2 + 0].push_back(vars.size());
213         nodes[x * 2 + 1].push_back(vars.size());
214         vars.push_back(model.addVar(0, rc, 0, GRB_INTEGER));
215         edges.push_back(std::make_pair(v, -1));
216     }
compute()217     virtual int compute() {
218         std::cerr << "compute" << std::endl;
219         int ns = nodes.size() / 2;
220 
221         int flow;
222         for (int i = 1; i < ns - 1; ++i) {
223             GRBLinExpr cons = 0;
224             for (auto n : nodes[2 * i + 0]) cons += vars[n];
225             for (auto n : nodes[2 * i + 1]) cons -= vars[n];
226             model.addConstr(cons == 0);
227         }
228 
229         // first pass, maximum flow
230         GRBLinExpr outbound = 0;
231         {
232             lprintf("first pass\n");
233             for (auto& n : nodes[0]) outbound += vars[n];
234             for (auto& n : nodes[1]) outbound -= vars[n];
235             model.setObjective(outbound, GRB_MAXIMIZE);
236             model.optimize();
237 
238             flow = (int)model.get(GRB_DoubleAttr_ObjVal);
239             lprintf("Gurobi result: %d\n", flow);
240         }
241 
242         // second pass, minimum cost flow
243         {
244             lprintf("second pass\n");
245             model.addConstr(outbound == flow);
246             GRBLinExpr cost = 0;
247             for (auto& v : vars) cost += v;
248             model.setObjective(cost, GRB_MINIMIZE);
249             model.optimize();
250 
251             double optimal_cost = (int)model.get(GRB_DoubleAttr_ObjVal);
252             lprintf("Gurobi result: %.3f\n", optimal_cost);
253         }
254         return flow;
255     }
applyTo(std::vector<Vector2i> & edge_diff)256     virtual void applyTo(std::vector<Vector2i>& edge_diff) { assert(0); };
257 
258    private:
259     GRBEnv env = GRBEnv();
260     GRBModel model = GRBModel(env);
261     std::vector<GRBVar> vars;
262     std::vector<std::pair<int, int>> edges;
263     std::vector<std::vector<int>> nodes;
264 };
265 
266 #endif
267 
268 class ECMaxFlowHelper : public MaxFlowHelper {
269    public:
270     struct FlowInfo {
271         int id;
272         int capacity, flow;
273         int v, d;
274         FlowInfo* rev;
275     };
276     struct SearchInfo {
SearchInfoqflow::ECMaxFlowHelper::SearchInfo277         SearchInfo(int _id, int _prev_id, FlowInfo* _info)
278             : id(_id), prev_id(_prev_id), info(_info) {}
279         int id;
280         int prev_id;
281         FlowInfo* info;
282     };
ECMaxFlowHelper()283     ECMaxFlowHelper() { num = 0; }
284     int num;
285     std::vector<FlowInfo*> variable_to_edge;
resize(int n,int m)286     void resize(int n, int m) {
287         graph.resize(n);
288         variable_to_edge.resize(m, 0);
289         num = n;
290     }
addEdge(int x,int y,int c,int rc,int v,int cost=0)291     void addEdge(int x, int y, int c, int rc, int v, int cost = 0) {
292         FlowInfo flow;
293         flow.id = y;
294         flow.capacity = c;
295         flow.flow = 0;
296         flow.v = v;
297         flow.d = -1;
298         graph[x].push_back(flow);
299         auto& f1 = graph[x].back();
300         flow.id = x;
301         flow.capacity = rc;
302         flow.flow = 0;
303         flow.v = v;
304         flow.d = 1;
305         graph[y].push_back(flow);
306         auto& f2 = graph[y].back();
307         f2.rev = &f1;
308         f1.rev = &f2;
309     }
compute()310     int compute() {
311         int total_flow = 0;
312         int count = 0;
313         while (true) {
314             count += 1;
315             std::vector<int> vhash(num, 0);
316             std::vector<SearchInfo> q;
317             q.push_back(SearchInfo(0, -1, 0));
318             vhash[0] = 1;
319             int q_front = 0;
320             bool found = false;
321             while (q_front < q.size()) {
322                 int vert = q[q_front].id;
323                 for (auto& l : graph[vert]) {
324                     if (vhash[l.id] || l.capacity <= l.flow) continue;
325                     q.push_back(SearchInfo(l.id, q_front, &l));
326                     vhash[l.id] = 1;
327                     if (l.id == num - 1) {
328                         found = true;
329                         break;
330                     }
331                 }
332                 if (found) break;
333                 q_front += 1;
334             }
335             if (q_front == q.size()) break;
336             int loc = q.size() - 1;
337             while (q[loc].prev_id != -1) {
338                 q[loc].info->flow += 1;
339                 q[loc].info->rev->flow -= 1;
340                 loc = q[loc].prev_id;
341                 // int prev_v = q[loc].id;
342                 // applyFlow(prev_v, current_v, 1);
343                 // applyFlow(current_v, prev_v, -1);
344             }
345             total_flow += 1;
346         }
347         return total_flow;
348     }
applyTo(std::vector<Vector2i> & edge_diff)349     void applyTo(std::vector<Vector2i>& edge_diff) {
350         for (int i = 0; i < graph.size(); ++i) {
351             for (auto& flow : graph[i]) {
352                 if (flow.flow > 0 && flow.v != -1) {
353                     if (flow.flow > 0) {
354                         edge_diff[flow.v / 2][flow.v % 2] += flow.d * flow.flow;
355                         if (abs(edge_diff[flow.v / 2][flow.v % 2]) > 2) {
356                         }
357                     }
358                 }
359             }
360         }
361     }
applyFlow(int v1,int v2,int flow)362     void applyFlow(int v1, int v2, int flow) {
363         for (auto& it : graph[v1]) {
364             if (it.id == v2) {
365                 it.flow += flow;
366                 break;
367             }
368         }
369     }
370     std::vector<std::list<FlowInfo>> graph;
371 };
372 
373 } // namespace qflow
374 
375 #endif
376