11#include <boost/graph/edmonds_karp_max_flow.hpp>
12#include <boost/graph/push_relabel_max_flow.hpp>
13#include <boost/graph/cycle_canceling.hpp>
14#include <boost/graph/find_flow_cost.hpp>
15#include <boost/graph/successive_shortest_path_nonnegative_weights.hpp>
48template <
typename NodeID>
51 std::map<std::pair<NodeID, NodeID>,
long> flow;
52 std::map<std::size_t, long> edge_flows_by_id;
76template <
typename NodeID>
80 std::map<std::pair<NodeID, NodeID>,
long> edge_flows;
81 std::map<std::size_t, long> edge_flows_by_id;
86template <
typename NodeID,
typename FlowEdgeDesc>
91 FlowEdgeDesc edge_desc;
94template <
typename NodeID>
96 using FlowTraits = boost::adjacency_list_traits<boost::vecS, boost::vecS, boost::directedS>;
97 using FlowGraph = boost::adjacency_list<
103 boost::edge_capacity_t,
106 boost::edge_residual_capacity_t,
108 boost::property<boost::edge_reverse_t, typename FlowTraits::edge_descriptor>
112 using CapacityMap =
typename boost::property_map<FlowGraph, boost::edge_capacity_t>::type;
113 using ResidualMap =
typename boost::property_map<FlowGraph, boost::edge_residual_capacity_t>::type;
114 using ReverseMap =
typename boost::property_map<FlowGraph, boost::edge_reverse_t>::type;
115 using FlowEdgeDesc =
typename boost::graph_traits<FlowGraph>::edge_descriptor;
117 FlowGraph flow_graph;
118 CapacityMap capacity;
119 ResidualMap residual;
121 std::vector<FlowEdgeRecord<NodeID, FlowEdgeDesc>> original_edges;
125 capacity(boost::get(boost::edge_capacity, flow_graph)),
126 residual(boost::get(boost::edge_residual_capacity, flow_graph)),
127 reverse(boost::get(boost::edge_reverse, flow_graph)) {}
130template <
typename NodeID>
132 using FlowTraits = boost::adjacency_list_traits<boost::vecS, boost::vecS, boost::directedS>;
133 using FlowGraph = boost::adjacency_list<
139 boost::edge_weight_t,
142 boost::edge_capacity_t,
145 boost::edge_residual_capacity_t,
147 boost::property<boost::edge_reverse_t, typename FlowTraits::edge_descriptor>
152 using WeightMap =
typename boost::property_map<FlowGraph, boost::edge_weight_t>::type;
153 using CapacityMap =
typename boost::property_map<FlowGraph, boost::edge_capacity_t>::type;
154 using ResidualMap =
typename boost::property_map<FlowGraph, boost::edge_residual_capacity_t>::type;
155 using ReverseMap =
typename boost::property_map<FlowGraph, boost::edge_reverse_t>::type;
156 using FlowEdgeDesc =
typename boost::graph_traits<FlowGraph>::edge_descriptor;
158 FlowGraph flow_graph;
160 CapacityMap capacity;
161 ResidualMap residual;
163 std::vector<FlowEdgeRecord<NodeID, FlowEdgeDesc>> original_edges;
167 weight(boost::get(boost::edge_weight, flow_graph)),
168 capacity(boost::get(boost::edge_capacity, flow_graph)),
169 residual(boost::get(boost::edge_residual_capacity, flow_graph)),
170 reverse(boost::get(boost::edge_reverse, flow_graph)) {}
173template <
typename FlowState>
174void add_flow_vertices(FlowState& state, std::size_t count) {
175 for (std::size_t i = 0; i < count; ++i) {
176 boost::add_vertex(state.flow_graph);
180template <
typename FlowState>
181auto add_capacity_edge_pair(FlowState& state, std::size_t source_index, std::size_t target_index,
long capacity_value) {
182 auto [edge, added] = boost::add_edge(source_index, target_index, state.flow_graph);
183 auto [reverse_edge, reverse_added] = boost::add_edge(target_index, source_index, state.flow_graph);
186 state.capacity[edge] = capacity_value;
187 state.capacity[reverse_edge] = 0;
188 state.reverse[edge] = reverse_edge;
189 state.reverse[reverse_edge] = edge;
193template <
typename GraphWrapper,
typename FlowState,
typename EdgeIdFn,
typename CapacityFn>
194void add_capacity_flow_edges(
195 const GraphWrapper& graph,
197 EdgeIdFn&& edge_id_for,
198 CapacityFn&& capacity_for
200 const auto& impl = graph.get_impl();
201 for (
auto [eit, eend] = boost::edges(impl); eit != eend; ++eit) {
202 const auto source = boost::source(*eit, impl);
203 const auto target = boost::target(*eit, impl);
204 const auto source_index = graph.get_vertex_index(source);
205 const auto target_index = graph.get_vertex_index(target);
206 const auto& source_id = graph.get_node_id(source);
207 const auto& target_id = graph.get_node_id(target);
208 const auto edge_id = edge_id_for(*eit);
209 const auto edge = add_capacity_edge_pair(state, source_index, target_index, capacity_for(edge_id));
210 state.original_edges.push_back({edge_id, source_id, target_id, edge});
214template <
typename GraphWrapper,
typename FlowState,
typename EdgeIdFn,
typename CapacityFn,
typename WeightFn>
215void add_weighted_flow_edges(
216 const GraphWrapper& graph,
218 EdgeIdFn&& edge_id_for,
219 CapacityFn&& capacity_for,
220 WeightFn&& weight_for
222 const auto& impl = graph.get_impl();
223 for (
auto [eit, eend] = boost::edges(impl); eit != eend; ++eit) {
224 const auto source = boost::source(*eit, impl);
225 const auto target = boost::target(*eit, impl);
226 const auto source_index = graph.get_vertex_index(source);
227 const auto target_index = graph.get_vertex_index(target);
228 const auto& source_id = graph.get_node_id(source);
229 const auto& target_id = graph.get_node_id(target);
230 const auto edge_id = edge_id_for(*eit);
231 const auto edge = add_capacity_edge_pair(state, source_index, target_index, capacity_for(edge_id));
232 const auto reverse_edge = state.reverse[edge];
233 state.weight[edge] = weight_for(edge_id);
234 state.weight[reverse_edge] = -state.weight[edge];
235 state.original_edges.push_back({edge_id, source_id, target_id, edge});
239template <
typename NodeID,
typename FlowEdgeDesc,
typename CapacityMap,
typename Res
idualMap>
241 const std::vector<FlowEdgeRecord<NodeID, FlowEdgeDesc>>& original_edges,
242 const CapacityMap& capacity,
243 const ResidualMap& residual,
244 std::map<std::pair<NodeID, NodeID>,
long>& endpoint_flows,
245 std::map<std::size_t, long>& edge_flows_by_id
247 for (
const auto& edge : original_edges) {
248 const long flow_value = capacity[edge.edge_desc] - residual[edge.edge_desc];
249 endpoint_flows[{edge.source_id, edge.target_id}] += flow_value;
250 edge_flows_by_id[edge.edge_id] = flow_value;
254template <
typename NodeID>
262template <
typename GraphWrapper>
263auto& min_cost_flow_cache() {
264 using NodeID =
typename GraphWrapper::NodeType;
265 static std::map<const void*, std::unique_ptr<MinCostFlowState<NodeID>>> cache;
269template <
typename GraphWrapper>
270auto& invalidated_min_cost_flow_graphs() {
271 static std::set<const void*> invalidated;
275template <
typename GraphWrapper>
276auto& min_cost_flow_cache_mutex() {
277 static std::mutex mutex;
283template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
285 static void invalidate(
const void* graph_ptr) {
287 auto& cache = detail::min_cost_flow_cache<Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>>();
288 if (cache.erase(graph_ptr) > 0) {
289 detail::invalidated_min_cost_flow_graphs<Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>>().insert(graph_ptr);
293 static void clear(
const void* graph_ptr) {
295 auto& cache = detail::min_cost_flow_cache<Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>>();
296 auto& invalidated = detail::invalidated_min_cost_flow_graphs<Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>>();
297 cache.erase(graph_ptr);
298 invalidated.erase(graph_ptr);
323template <
typename NodeID>
326 std::vector<NodeID> reachable;
327 std::vector<NodeID> non_reachable;
328 std::vector<std::pair<NodeID, NodeID>> cut_edges;
329 std::vector<std::size_t> cut_edge_ids;
332template <
typename GraphWrapper>
343[[deprecated(
"Use G.edmonds_karp_maximum_flow(source, target, capacity_attr) instead.")]]
344auto edmonds_karp_maximum_flow(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& capacity_attr =
"capacity") {
345 return G.edmonds_karp_maximum_flow(source_id, target_id, capacity_attr);
348template <
typename GraphWrapper>
359[[deprecated(
"Use G.push_relabel_maximum_flow_result(source, target, capacity_attr) instead.")]]
360auto push_relabel_maximum_flow_result(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& capacity_attr =
"capacity") {
361 return G.push_relabel_maximum_flow_result(source_id, target_id, capacity_attr);
364template <
typename GraphWrapper>
375[[deprecated(
"Use G.maximum_flow(source, target, capacity_attr) instead.")]]
376auto maximum_flow(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& capacity_attr =
"capacity") {
377 return G.maximum_flow(source_id, target_id, capacity_attr);
380template <
typename GraphWrapper>
391[[deprecated(
"Use G.minimum_cut(source, target, capacity_attr) instead.")]]
392auto minimum_cut(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& capacity_attr =
"capacity") {
393 return G.minimum_cut(source_id, target_id, capacity_attr);
396template <
typename GraphWrapper>
408[[deprecated(
"Use G.max_flow_min_cost_cycle_canceling(source, target, capacity_attr, weight_attr) instead.")]]
409auto max_flow_min_cost_cycle_canceling(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& capacity_attr =
"capacity",
const std::string& weight_attr =
"weight") {
410 return G.max_flow_min_cost_cycle_canceling(source_id, target_id, capacity_attr, weight_attr);
413template <
typename GraphWrapper>
425[[deprecated(
"Use G.push_relabel_maximum_flow(source, target, capacity_attr, weight_attr) instead.")]]
426long push_relabel_maximum_flow(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& capacity_attr =
"capacity",
const std::string& weight_attr =
"weight") {
427 return G.push_relabel_maximum_flow(source_id, target_id, capacity_attr, weight_attr);
430template <
typename GraphWrapper>
438[[deprecated(
"Use G.cycle_canceling(weight_attr) instead.")]]
439auto cycle_canceling(
const GraphWrapper& G,
const std::string& weight_attr =
"weight") {
440 return G.cycle_canceling(weight_attr);
443template <
typename GraphWrapper>
455[[deprecated(
"Use G.successive_shortest_path_nonnegative_weights(source, target, capacity_attr, weight_attr) instead.")]]
456auto successive_shortest_path_nonnegative_weights(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& capacity_attr =
"capacity",
const std::string& weight_attr =
"weight") {
457 return G.successive_shortest_path_nonnegative_weights(source_id, target_id, capacity_attr, weight_attr);
460template <
typename GraphWrapper>
472[[deprecated(
"Use G.max_flow_min_cost_successive_shortest_path(source, target, capacity_attr, weight_attr) instead.")]]
473auto max_flow_min_cost_successive_shortest_path(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& capacity_attr =
"capacity",
const std::string& weight_attr =
"weight") {
474 return G.max_flow_min_cost_successive_shortest_path(source_id, target_id, capacity_attr, weight_attr);
476template <
typename GraphWrapper>
488[[deprecated(
"Use G.max_flow_min_cost(source, target, capacity_attr, weight_attr) instead.")]]
489auto max_flow_min_cost(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& capacity_attr =
"capacity",
const std::string& weight_attr =
"weight") {
490 return G.max_flow_min_cost(source_id, target_id, capacity_attr, weight_attr);
493template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
495 if (!has_node(source_id) || !has_node(target_id))
throw std::runtime_error(
"Flow setup failed: source or target node not found.");
497 detail::add_flow_vertices(state, get_bgl_to_id_map().size());
498 detail::add_capacity_flow_edges(
501 [
this](EdgeDesc edge) {
return get_edge_id(edge); },
502 [
this, &capacity_attr](std::size_t edge_id) {
return get_edge_flow_capacity(edge_id, capacity_attr); }
505 const long flow_value = boost::edmonds_karp_max_flow(
507 get_vertex_index(get_id_to_bgl_map().at(source_id)),
508 get_vertex_index(get_id_to_bgl_map().at(target_id))
511 result.value = flow_value;
512 detail::fill_flow_views(state.original_edges, state.capacity, state.residual, result.flow, result.edge_flows_by_id);
516template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
518 if (!has_node(source_id) || !has_node(target_id))
throw std::runtime_error(
"Flow setup failed: source or target node not found.");
520 detail::add_flow_vertices(state, get_bgl_to_id_map().size());
521 detail::add_capacity_flow_edges(
524 [
this](EdgeDesc edge) {
return get_edge_id(edge); },
525 [
this, &capacity_attr](std::size_t edge_id) {
return get_edge_flow_capacity(edge_id, capacity_attr); }
528 const long flow_value = boost::push_relabel_max_flow(
530 get_vertex_index(get_id_to_bgl_map().at(source_id)),
531 get_vertex_index(get_id_to_bgl_map().at(target_id))
534 result.value = flow_value;
535 detail::fill_flow_views(state.original_edges, state.capacity, state.residual, result.flow, result.edge_flows_by_id);
539template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
540auto Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>::maximum_flow(
const NodeID& source_id,
const NodeID& target_id,
const std::string& capacity_attr)
const {
return edmonds_karp_maximum_flow(source_id, target_id, capacity_attr); }
542template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
544 if (!has_node(source_id) || !has_node(target_id))
throw std::runtime_error(
"Flow setup failed: source or target node not found.");
546 const auto& index_to_node = get_bgl_to_id_map();
547 detail::add_flow_vertices(state, index_to_node.size());
548 detail::add_capacity_flow_edges(
551 [
this](EdgeDesc edge) {
return get_edge_id(edge); },
552 [
this, &capacity_attr](std::size_t edge_id) {
return get_edge_flow_capacity(edge_id, capacity_attr); }
554 const auto source_index = get_vertex_index(get_id_to_bgl_map().at(source_id));
555 const auto target_index = get_vertex_index(get_id_to_bgl_map().at(target_id));
556 const long cut_value = boost::edmonds_karp_max_flow(state.flow_graph, source_index, target_index);
557 std::vector<bool> visited(index_to_node.size(),
false);
558 std::queue<std::size_t> q;
559 visited[source_index] =
true;
560 q.push(source_index);
562 const auto current = q.front();
564 for (
auto [eit, eend] = boost::out_edges(current, state.flow_graph); eit != eend; ++eit) {
565 const auto next = boost::target(*eit, state.flow_graph);
566 if (!visited[next] && state.residual[*eit] > 0) { visited[next] =
true; q.push(next); }
570 result.value = cut_value;
571 for (std::size_t i = 0; i < index_to_node.size(); ++i) {
572 if (visited[i]) result.reachable.push_back(index_to_node[i]);
573 else result.non_reachable.push_back(index_to_node[i]);
575 for (
auto [eit, eend] = boost::edges(g); eit != eend; ++eit) {
576 const auto source = boost::source(*eit, g);
577 const auto target = boost::target(*eit, g);
578 const auto source_index_for_cut = get_vertex_index(source);
579 const auto target_index_for_cut = get_vertex_index(target);
580 if (visited[source_index_for_cut] && !visited[target_index_for_cut]) {
581 result.cut_edges.emplace_back(get_node_id(source), get_node_id(target));
582 result.cut_edge_ids.push_back(get_edge_id(*eit));
588template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
590 if (!has_node(source_id) || !has_node(target_id))
throw std::runtime_error(
"Flow setup failed: source or target node not found.");
592 detail::add_flow_vertices(state, get_bgl_to_id_map().size());
593 detail::add_weighted_flow_edges(
596 [
this](EdgeDesc edge) {
return get_edge_id(edge); },
597 [
this, &capacity_attr](std::size_t edge_id) {
return get_edge_flow_capacity(edge_id, capacity_attr); },
598 [
this, &weight_attr](std::size_t edge_id) {
return static_cast<long>(get_edge_numeric_attr(edge_id, weight_attr)); }
600 boost::push_relabel_max_flow(
602 get_vertex_index(get_id_to_bgl_map().at(source_id)),
603 get_vertex_index(get_id_to_bgl_map().at(target_id))
605 boost::cycle_canceling(state.flow_graph);
606 const long cost = boost::find_flow_cost(state.flow_graph);
609 detail::fill_flow_views(state.original_edges, state.capacity, state.residual, result.edge_flows, result.edge_flows_by_id);
610 for (
const auto& edge : state.original_edges) {
611 if (edge.source_id == source_id) {
612 result.flow += result.edge_flows_by_id[edge.edge_id];
618template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
620 if (!has_node(source_id) || !has_node(target_id))
throw std::runtime_error(
"Flow setup failed: source or target node not found.");
621 auto state = std::make_unique<detail::MinCostFlowState<NodeID>>();
622 state->source_id = source_id;
623 state->target_id = target_id;
624 detail::add_flow_vertices(*state, get_bgl_to_id_map().size());
625 detail::add_weighted_flow_edges(
628 [
this](EdgeDesc edge) {
return get_edge_id(edge); },
629 [
this, &capacity_attr](std::size_t edge_id) {
return get_edge_flow_capacity(edge_id, capacity_attr); },
630 [
this, &weight_attr](std::size_t edge_id) {
return static_cast<long>(get_edge_numeric_attr(edge_id, weight_attr)); }
632 state->value = boost::push_relabel_max_flow(
634 get_vertex_index(get_id_to_bgl_map().at(source_id)),
635 get_vertex_index(get_id_to_bgl_map().at(target_id))
637 const long flow_value = state->value;
640 auto& cache = detail::min_cost_flow_cache<Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>>();
641 auto& invalidated = detail::invalidated_min_cost_flow_graphs<Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>>();
642 cache[
static_cast<const void*
>(
this)] = std::move(state);
643 invalidated.erase(
static_cast<const void*
>(
this));
648template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
651 auto& cache = detail::min_cost_flow_cache<Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>>();
652 auto& invalidated = detail::invalidated_min_cost_flow_graphs<Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>>();
653 auto it = cache.find(
static_cast<const void*
>(
this));
654 if (it == cache.end()) {
655 if (invalidated.contains(
static_cast<const void*
>(
this))) {
656 throw std::runtime_error(
"Min-cost-flow state invalidated by graph mutation: rerun push_relabel_maximum_flow(...) before cycle_canceling().");
658 throw std::runtime_error(
"Min-cost-flow state unavailable: run push_relabel_maximum_flow(...) first.");
660 auto& state = *it->second;
661 for (
const auto& edge : state.original_edges) {
662 state.weight[edge.edge_desc] =
static_cast<long>(get_edge_numeric_attr(edge.edge_id, weight_attr));
663 const auto rev = state.reverse[edge.edge_desc];
664 state.weight[rev] = -state.weight[edge.edge_desc];
666 boost::cycle_canceling(state.flow_graph);
667 state.cost = boost::find_flow_cost(state.flow_graph);
671template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
673 if (!has_node(source_id) || !has_node(target_id))
throw std::runtime_error(
"Flow setup failed: source or target node not found.");
675 detail::add_flow_vertices(state, get_bgl_to_id_map().size());
676 detail::add_weighted_flow_edges(
679 [
this](EdgeDesc edge) {
return get_edge_id(edge); },
680 [
this, &capacity_attr](std::size_t edge_id) {
return get_edge_flow_capacity(edge_id, capacity_attr); },
681 [
this, &weight_attr](std::size_t edge_id) {
return static_cast<long>(get_edge_numeric_attr(edge_id, weight_attr)); }
683 const auto source_index = get_vertex_index(get_id_to_bgl_map().at(source_id));
684 const auto target_index = get_vertex_index(get_id_to_bgl_map().at(target_id));
685 boost::successive_shortest_path_nonnegative_weights(state.flow_graph, source_index, target_index);
687 for (
auto [eit, eend] = boost::out_edges(source_index, state.flow_graph); eit != eend; ++eit) {
688 flow_value += state.capacity[*eit] - state.residual[*eit];
690 const long cost = boost::find_flow_cost(state.flow_graph);
692 result.flow = flow_value;
694 detail::fill_flow_views(state.original_edges, state.capacity, state.residual, result.edge_flows, result.edge_flows_by_id);
698template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
703template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
Attribute-bearing edge insertion helpers and attribute-oriented graph method definitions.
Graph wrapper around Boost Graph Library with Python-inspired helpers.
Definition graph.hpp:288
auto edmonds_karp_maximum_flow(const NodeID &source_id, const NodeID &target_id, const std::string &capacity_attr="capacity") const
Computes a maximum flow using the Edmonds-Karp algorithm.
Definition flow.hpp:494
auto successive_shortest_path_nonnegative_weights(const NodeID &source_id, const NodeID &target_id, const std::string &capacity_attr="capacity", const std::string &weight_attr="weight") const
Computes a max-flow min-cost result using successive shortest path.
Definition flow.hpp:672
auto max_flow_min_cost(const NodeID &source_id, const NodeID &target_id, const std::string &capacity_attr="capacity", const std::string &weight_attr="weight") const
Convenience alias for the default max-flow min-cost wrapper.
Definition flow.hpp:704
auto max_flow_min_cost_successive_shortest_path(const NodeID &source_id, const NodeID &target_id, const std::string &capacity_attr="capacity", const std::string &weight_attr="weight") const
Convenience alias for successive_shortest_path_nonnegative_weights().
Definition flow.hpp:699
auto minimum_cut(const NodeID &source_id, const NodeID &target_id, const std::string &capacity_attr="capacity") const
Computes a minimum cut between source and target using the named capacity attribute.
Definition flow.hpp:543
auto maximum_flow(const NodeID &source_id, const NodeID &target_id, const std::string &capacity_attr="capacity") const
Computes the maximum flow value and edge assignments using the named capacity attribute.
Definition flow.hpp:540
long push_relabel_maximum_flow(const NodeID &source_id, const NodeID &target_id, const std::string &capacity_attr="capacity", const std::string &weight_attr="weight") const
Runs push-relabel and stages residual state for a later cycle_canceling() call. Any later graph mutat...
Definition flow.hpp:619
auto cycle_canceling(const std::string &weight_attr="weight") const
Runs cycle canceling on the previously cached residual network.
Definition flow.hpp:649
auto max_flow_min_cost_cycle_canceling(const NodeID &source_id, const NodeID &target_id, const std::string &capacity_attr="capacity", const std::string &weight_attr="weight") const
Computes a max-flow min-cost result using cycle canceling.
Definition flow.hpp:589
auto push_relabel_maximum_flow_result(const NodeID &source_id, const NodeID &target_id, const std::string &capacity_attr="capacity") const
Computes a maximum flow using push-relabel and returns edge assignments.
Definition flow.hpp:517
auto max_flow_min_cost(const GraphWrapper &G, const typename GraphWrapper::NodeType &source_id, const typename GraphWrapper::NodeType &target_id, const std::string &capacity_attr="capacity", const std::string &weight_attr="weight")
Deprecated free-function alias for G.max_flow_min_cost(...).
Definition flow.hpp:489
auto max_flow_min_cost_successive_shortest_path(const GraphWrapper &G, const typename GraphWrapper::NodeType &source_id, const typename GraphWrapper::NodeType &target_id, const std::string &capacity_attr="capacity", const std::string &weight_attr="weight")
Deprecated free-function alias for G.max_flow_min_cost_successive_shortest_path(.....
Definition flow.hpp:473
auto cycle_canceling(const GraphWrapper &G, const std::string &weight_attr="weight")
Deprecated free-function alias for G.cycle_canceling(weight_attr).
Definition flow.hpp:439
auto maximum_flow(const GraphWrapper &G, const typename GraphWrapper::NodeType &source_id, const typename GraphWrapper::NodeType &target_id, const std::string &capacity_attr="capacity")
Deprecated free-function alias for G.maximum_flow(...).
Definition flow.hpp:376
auto edmonds_karp_maximum_flow(const GraphWrapper &G, const typename GraphWrapper::NodeType &source_id, const typename GraphWrapper::NodeType &target_id, const std::string &capacity_attr="capacity")
Deprecated free-function alias for G.edmonds_karp_maximum_flow(...).
Definition flow.hpp:344
auto push_relabel_maximum_flow_result(const GraphWrapper &G, const typename GraphWrapper::NodeType &source_id, const typename GraphWrapper::NodeType &target_id, const std::string &capacity_attr="capacity")
Deprecated free-function alias for G.push_relabel_maximum_flow_result(...).
Definition flow.hpp:360
auto minimum_cut(const GraphWrapper &G, const typename GraphWrapper::NodeType &source_id, const typename GraphWrapper::NodeType &target_id, const std::string &capacity_attr="capacity")
Deprecated free-function alias for G.minimum_cut(...).
Definition flow.hpp:392
long push_relabel_maximum_flow(const GraphWrapper &G, const typename GraphWrapper::NodeType &source_id, const typename GraphWrapper::NodeType &target_id, const std::string &capacity_attr="capacity", const std::string &weight_attr="weight")
Deprecated free-function alias for G.push_relabel_maximum_flow(...).
Definition flow.hpp:426
auto max_flow_min_cost_cycle_canceling(const GraphWrapper &G, const typename GraphWrapper::NodeType &source_id, const typename GraphWrapper::NodeType &target_id, const std::string &capacity_attr="capacity", const std::string &weight_attr="weight")
Deprecated free-function alias for G.max_flow_min_cost_cycle_canceling(...).
Definition flow.hpp:409
auto successive_shortest_path_nonnegative_weights(const GraphWrapper &G, const typename GraphWrapper::NodeType &source_id, const typename GraphWrapper::NodeType &target_id, const std::string &capacity_attr="capacity", const std::string &weight_attr="weight")
Deprecated free-function alias for G.successive_shortest_path_nonnegative_weights(....
Definition flow.hpp:456
Precise edge_id-based multigraph operations and edge-aware attribute access.
Result of a maximum-flow computation.
Definition flow.hpp:49
Result of a min-cost max-flow computation.
Definition flow.hpp:77
Result of a minimum-cut computation.
Definition flow.hpp:324