Assume I have a simple graph with three vertices, How could I change output edge of 0 to 2 instead of 1
Note: I don't want to do it while creating the graph.
Assume I have a simple graph with three vertices, How could I change output edge of 0 to 2 instead of 1
Note: I don't want to do it while creating the graph.
Assuming the simple graph that you left out of the question:
auto simple_graph() {
boost::adjacency_list<> g;
add_edge(0, 1, g);
add_edge(1, 2, g);
return g;
}
Now the absolute simplest you can do for this graph model is
// change (0,1) to (0,2):
remove_edge(0, 1, g);
add_edge(0, 2, g);
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
auto simple_graph() {
boost::adjacency_list<> g;
add_edge(0, 1, g);
add_edge(1, 2, g);
return g;
}
int main() {
auto g = simple_graph();
write_graphviz(std::cout, g);
// change (0,1) to (0,2):
remove_edge(0, 1, g);
add_edge(0, 2, g);
write_graphviz(std::cout, g);
}
Prints
digraph G {
0;
1;
2;
0->1 ;
1->2 ;
}
digraph G {
0;
1;
2;
0->2 ;
1->2 ;
}
So indeed
becomes

In case you had other graph types, other approaches become natural:
#include <boost/graph/edge_list.hpp>
#include <boost/graph/graphviz.hpp>
int main() {
std::vector edges{std::pair{0, 1}, {1, 2}};
boost::edge_list g(edges.begin(), edges.end());
// change (0,1) to (0,2):
edges[0].second = 2;
}
I'd write a 5-line helper function:
template <typename V, typename G>
void update_edge_target(V source, V target, V new_target, G& g) {
if (auto [e, exists] = edge(source, target, g); exists) {
auto prop = std::move(g[e]);
remove_edge(e, g);
add_edge(source, new_target, prop, g);
}
}
Note: I don't think BGL supports move semantics, so splitting the last line could improve efficiency:
e = add_edge(source, new_target, g); g[e] = std::move(prop);
See it Live On Compiler Explorer
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
struct EdgeProps {
std::map<int, std::string> lots;
std::string more;
};
auto simple_graph() {
using namespace boost;
adjacency_list<vecS, vecS, directedS, no_property, EdgeProps> g;
add_edge(0, 1,
{{
{1, "one"},
{2, "two"},
{3, "three"},
},
"very heavy data!"},
g);
add_edge(1, 2,
{{
{4, "four"},
{5, "five"},
{6, "size"},
},
"needs preserving"},
g);
return g;
}
template <typename V, typename G>
void update_edge_target(V source, V target, V new_target, G& g) {
if (auto [e, exists] = edge(source, target, g); exists) {
auto prop = std::move(g[e]);
remove_edge(e, g);
add_edge(source, new_target, prop, g);
}
}
// for debug output
#include <fmt/ranges.h>
template <typename G> struct writer : boost::default_writer {
G const& g;
explicit writer(G const& g) : g(g) {}
void operator()(std::ostream& os, auto const& desc) const { handle(os, g[desc]); }
private:
void handle(std::ostream& os, boost::no_property) const { os << "[]"; }
void handle(std::ostream& os, EdgeProps const& ep) const {
os << "[label=" << boost::escape_dot_string(ep.more)
<< ",extra=" << boost::escape_dot_string(fmt::format("{}", ep.lots))
<< "]";
}
};
int main() {
auto g = simple_graph();
writer w{g};
write_graphviz(std::cout, g, w, w);
// change (0,1) to (0,2):
update_edge_target(0, 1, 2, g);
write_graphviz(std::cout, g, w, w);
}
Prints
digraph G {
0[];
1[];
2[];
0->1 [label="very heavy data!",extra="{1: \"one\", 2: \"two\", 3: \"three\"}"];
1->2 [label="needs preserving",extra="{4: \"four\", 5: \"five\", 6: \"size\"}"];
}
digraph G {
0[];
1[];
2[];
0->2 [label="very heavy data!",extra="{1: \"one\", 2: \"two\", 3: \"three\"}"];
1->2 [label="needs preserving",extra="{4: \"four\", 5: \"five\", 6: \"size\"}"];
}
Which renders:
to
