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