I am having trouble calculating the maximum flow for a given graph using boost::push_relabel_max_flow. I've written the following code:
std::map<Graph::edge_descriptor, long> edge2rescap;
boost::associative_property_map<std::map<Graph::edge_descriptor, long> > out(edge2rescap);
int flow_val = boost::push_relabel_max_flow (g_transformed_for_max_flow, v_start, v_end, capacity_map(boost::get(&EdgeProps::edge_capacity, g_transformed_for_max_flow))
.reverse_edge_map(boost::get(&EdgeProps::reverse_edge, g_transformed_for_max_flow))
.vertex_index_map(boost::get(boost::vertex_index, g_transformed_for_max_flow))
.residual_capacity_map(out));
The graph was defined as follows:
typedef boost::adjacency_list_traits<boost::vecS, boost::vecS, boost::directedS> Graph;
struct VertexProperty{ };
struct EdgeProps{
// long edge_capacity;
long edge_capacity;
Graph::edge_descriptor reverse_edge;
EdgeProps(long capacity, Graph::edge_descriptor reverseEdge): edge_capacity(capacity), reverse_edge(reverseEdge){};
EdgeProps(long capacity): edge_capacity(capacity){};
EdgeProps(){};
};
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertexProperty, EdgeProps > DirectedGraph_maxflow;
typedef boost::graph_traits <DirectedGraph_maxflow>::edge_iterator edgeIt_dir;
typedef boost::graph_traits<DirectedGraph_maxflow>::out_edge_iterator out_edge_iterator;
My code compiles perfectly for my simple graph example. However, strangely it does so only if all capacities are chosen equally. If i change just one capacity the compiler outputs: Assertion `algo.is_flow()' failed.
Maybe someone has had this issue once before and knows how to solve it. If not, it would be nice if someone of you could maybe share with me a small working example (using a non-trivial graph). Thank you in advance for your responses.
Without self-contained example, my best bet is you invoke UB because the back edges are inconsistent?
Perhaps you can edit this Live Example to demonstrate the issue you're having:
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/push_relabel_max_flow.hpp>
#include <fmt/ranges.h>
#include <fmt/ostream.h>
using Traits = boost::adjacency_list_traits<boost::vecS, boost::vecS, boost::directedS>;
using V = Traits::vertex_descriptor;
using E = Traits::edge_descriptor;
template <> struct fmt::formatter<E> : fmt::ostream_formatter {};
struct VertexProps {};
struct EdgeProps {
long edge_capacity = 0;
E reverse_edge = {};
EdgeProps(long capacity = 0, E reverseEdge = {}) //
: edge_capacity(capacity)
, reverse_edge(reverseEdge){};
};
using Graph =
boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertexProps, EdgeProps>;
int main() {
Graph g(5);
auto ecap = get(&EdgeProps::edge_capacity, g);
auto reve = get(&EdgeProps::reverse_edge, g);
auto insert = [&](V s, V t, EdgeProps p) {
auto fwd = add_edge(s, t, p, g).first;
auto bck = add_edge(t, s, {}, g).first;
reve[fwd] = bck;
reve[bck] = fwd;
};
insert(0, 1, {6});
insert(1, 2, {7});
insert(2, 3, {3});
insert(3, 4, {1});
V v_start = 1, v_end = 4;
std::map<E, long> residuals;
int flow_val = push_relabel_max_flow(
g, v_start, v_end,
capacity_map(ecap)
.reverse_edge_map(reve)
.residual_capacity_map(make_assoc_property_map(residuals)));
fmt::print("flow: {} residuals: {}\n", flow_val, residuals);
}
Printing
flow: 1 residuals: {(0,1): 6, (1,0): 0, (1,2): 6, (2,1): 1, (2,3): 2, (3,2): 1, (3,4): 0, (4,3): 1}