11#if !__has_include(<boost/graph/adjacency_list.hpp>)
12#error "FATAL: nxpp requires the Boost Graph Library (BGL)."
15#if defined(__GNUC__) && !defined(__clang__)
16#pragma GCC diagnostic push
17#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
19#include <boost/graph/adjacency_list.hpp>
20#include <boost/functional/hash.hpp>
21#if defined(__GNUC__) && !defined(__clang__)
22#pragma GCC diagnostic pop
51 typename OutEdgeSelector,
52 typename VertexSelector
58template <
typename GraphWrapper>
60 static void invalidate(
const void*) {}
61 static void clear(
const void*) {}
70enum vertex_wrapper_index_t { vertex_wrapper_index };
71BOOST_INSTALL_PROPERTY(vertex, wrapper_index);
77template <
typename GraphType,
bool HasWeight>
84 requires(
const T& lhs,
const T& rhs) {
85 { std::less<T>{}(lhs, rhs) } -> std::convertible_to<bool>;
90template <
typename GraphType>
92 using map_type =
typename boost::property_map<GraphType, boost::edge_weight_t>::type;
94 static map_type get(GraphType& g) {
95 return boost::get(boost::edge_weight, g);
99template <
typename GraphType>
103 static map_type get(GraphType&) {
108template <
typename Key,
typename Value>
111 using storage_type = std::map<Key, Value>;
112 using iterator =
typename storage_type::iterator;
113 using const_iterator =
typename storage_type::const_iterator;
115 Value& operator[](
const Key& key) {
119 const Value& operator[](
const Key& key)
const {
123 Value& at(
const Key& key) {
127 const Value& at(
const Key& key)
const {
131 iterator begin() {
return data.begin(); }
132 iterator end() {
return data.end(); }
133 const_iterator begin()
const {
return data.begin(); }
134 const_iterator end()
const {
return data.end(); }
135 const_iterator cbegin()
const {
return data.cbegin(); }
136 const_iterator cend()
const {
return data.cend(); }
142template <
typename Key,
typename Value>
145 using storage_type = std::vector<std::pair<Key, Value>>;
146 using iterator =
typename storage_type::iterator;
147 using const_iterator =
typename storage_type::const_iterator;
159 void reserve(std::size_t count) {
163 void push_back(
const Key& key,
const Value& value) {
164 data.emplace_back(key, value);
167 void push_back(
const Key& key, Value&& value) {
168 data.emplace_back(key, std::move(value));
171 Value& at(
const Key& key) {
173 if (it == data.end()) {
174 throw std::out_of_range(
"indexed_lookup_map::at");
179 const Value& at(
const Key& key)
const {
181 if (it == data.end()) {
182 throw std::out_of_range(
"indexed_lookup_map::at");
187 Value& operator[](
const Key& key) {
191 const Value& operator[](
const Key& key)
const {
195 bool contains(
const Key& key)
const {
196 return find(key) != data.end();
199 iterator find(
const Key& key) {
200 auto it = lower_bound_for(key);
201 if (it == data.end() || key < it->first) {
207 const_iterator find(
const Key& key)
const {
208 auto it = lower_bound_for(key);
209 if (it == data.end() || key < it->first) {
215 iterator begin() {
return data.begin(); }
216 iterator end() {
return data.end(); }
217 const_iterator begin()
const {
return data.begin(); }
218 const_iterator end()
const {
return data.end(); }
219 const_iterator cbegin()
const {
return data.cbegin(); }
220 const_iterator cend()
const {
return data.cend(); }
222 bool empty()
const {
return data.empty(); }
223 std::size_t size()
const {
return data.size(); }
226 iterator lower_bound_for(
const Key& key) {
227 return std::lower_bound(
231 [](
const auto& entry,
const Key& value) { return entry.first < value; }
235 const_iterator lower_bound_for(
const Key& key)
const {
236 return std::lower_bound(
240 [](
const auto& entry,
const Key& value) { return entry.first < value; }
250 typename NodeID = std::string,
251 typename EdgeWeight = double,
252 bool Directed =
false,
254 bool Weighted =
true,
255 typename OutEdgeSelector = boost::vecS,
256 typename VertexSelector = boost::vecS
274 using NodeType = NodeID;
275 using EdgeWeightType = EdgeWeight;
276 using OutEdgeListSelector = OutEdgeSelector;
277 using VertexListSelector = VertexSelector;
278 using DirectedSelector =
typename std::conditional<Directed, boost::bidirectionalS, boost::undirectedS>::type;
279 using VertexProperty = boost::property<
280 boost::vertex_name_t,
282 boost::property<boost::vertex_wrapper_index_t, std::size_t>
284 using EdgeProperty =
typename std::conditional<
286 boost::property<boost::edge_weight_t, EdgeWeight, boost::property<boost::edge_index_t, std::size_t>>,
287 boost::property<boost::edge_index_t, std::size_t>
289 using GraphType = boost::adjacency_list<OutEdgeSelector, VertexSelector, DirectedSelector,
290 VertexProperty, EdgeProperty>;
291 using VertexDesc =
typename boost::graph_traits<GraphType>::vertex_descriptor;
292 using EdgeDesc =
typename boost::graph_traits<GraphType>::edge_descriptor;
294 using VertexNameMap =
typename boost::property_map<GraphType, boost::vertex_name_t>::type;
295 using WrapperIndexMap =
typename boost::property_map<GraphType, boost::vertex_wrapper_index_t>::type;
296 using VertexIndexMap = WrapperIndexMap;
297 using EdgeIdMap =
typename boost::property_map<GraphType, boost::edge_index_t>::type;
298 using IdMap = std::map<NodeID, VertexDesc>;
299 using AttrMap = std::map<std::string, std::any>;
300 using NodeAttrStorage = std::map<NodeID, AttrMap>;
301 using EdgeAttrStorage = std::map<std::size_t, AttrMap>;
302 static constexpr bool is_directed = Directed;
303 static constexpr bool has_builtin_edge_weight = Weighted;
307 std::copy_constructible<NodeID>,
308 "nxpp::Graph requires NodeID to be copy-constructible because node IDs are stored and materialized across wrapper-owned containers."
312 std::equality_comparable<NodeID>,
313 "nxpp::Graph requires NodeID to support operator== because several wrapper result helpers compare reconstructed node IDs directly."
318 "nxpp::Graph requires NodeID to be orderable with std::less because wrapper-owned maps and key-sorted result containers rely on that ordering."
322 WeightMap weight_map;
323 VertexNameMap vertex_name_map;
324 VertexIndexMap vertex_index_map;
325 EdgeIdMap edge_id_map;
327 std::vector<NodeID> bgl_to_id;
328 std::size_t next_edge_id = 0;
329 NodeAttrStorage node_properties;
330 EdgeAttrStorage edge_properties;
334 !(Multi && std::is_same_v<OutEdgeSelector, boost::setS>),
335 "nxpp does not support Multi=true with boost::setS because setS suppresses parallel edges."
338 using EdgeAttrMap = AttrMap;
340 static std::any normalize_attr_any(std::any value) {
341 if (value.type() ==
typeid(
const char*)) {
342 return std::string(std::any_cast<const char*>(value));
344 if (value.type() ==
typeid(
char*)) {
345 return std::string(std::any_cast<char*>(value));
350 template <
typename T>
351 static std::any make_attr_any(
const T& value) {
352 if constexpr (std::is_convertible_v<T, const char*> && !std::is_same_v<std::decay_t<T>, std::string>) {
353 return std::string(value);
355 return std::any(value);
359 std::size_t vertex_index_of(VertexDesc v)
const {
360 return boost::get(vertex_index_map, v);
363 const NodeID& node_id_of(VertexDesc v)
const {
364 return boost::get(vertex_name_map, v);
367 template <
typename Value,
typename BuildValue>
370 result.reserve(id_to_bgl.size());
371 for (
const auto& [
id, desc] : id_to_bgl) {
372 result.push_back(
id, build_value(desc));
377 template <
typename Value>
379 const std::vector<std::optional<Value>>& values
382 for (
const auto& [
id, desc] : id_to_bgl) {
384 if (index < values.size() && values[index].has_value()) {
385 result.push_back(
id, *values[index]);
391 void rebuild_vertex_maps() {
395 std::size_t index = 0;
396 for (
auto [v, vend] = boost::vertices(g); v != vend; ++v, ++index) {
397 boost::put(vertex_index_map, *v, index);
398 NodeID
id = boost::get(vertex_name_map, *v);
400 bgl_to_id.push_back(
id);
404 VertexDesc get_or_create_vertex(
const NodeID&
id) {
405 auto it = id_to_bgl.find(
id);
406 if (it != id_to_bgl.end()) {
409 VertexDesc v = boost::add_vertex(g);
410 boost::put(vertex_name_map, v,
id);
411 boost::put(vertex_index_map, v, bgl_to_id.size());
413 bgl_to_id.push_back(
id);
417 std::size_t get_edge_id(EdgeDesc e)
const {
418 return boost::get(edge_id_map, e);
421 std::optional<EdgeDesc> try_find_edge_desc_by_id(std::size_t edge_id)
const {
422 for (
auto [e, eend] = boost::edges(g); e != eend; ++e) {
423 if (get_edge_id(*e) == edge_id) {
430 EdgeDesc get_edge_desc_by_id(std::size_t edge_id)
const {
431 auto edge_desc = try_find_edge_desc_by_id(edge_id);
432 if (!edge_desc.has_value()) {
433 throw std::runtime_error(
"Edge lookup failed: edge not found.");
438 std::vector<std::size_t> collect_edge_ids_between(VertexDesc u, VertexDesc v)
const {
440 for (
auto [e, eend] = boost::out_edges(u, g); e != eend; ++e) {
441 if (boost::target(*e, g) == v) {
442 edge_ids.push_back(get_edge_id(*e));
445 if constexpr (!Directed) {
447 for (
auto [e, eend] = boost::out_edges(v, g); e != eend; ++e) {
448 if (boost::target(*e, g) == u) {
449 edge_ids.push_back(get_edge_id(*e));
457 void erase_incident_edge_properties(VertexDesc v) {
459 for (
auto [e, eend] = boost::edges(g); e != eend; ++e) {
460 if (boost::source(*e, g) == v || boost::target(*e, g) == v) {
461 edge_ids.push_back(get_edge_id(*e));
465 edge_properties.erase(edge_id);
469 void assign_edge_attrs(EdgeDesc e,
const EdgeAttrMap& attrs) {
470 auto& edge_attr_map = edge_properties[get_edge_id(e)];
471 for (
const auto& [key, value] : attrs) {
472 edge_attr_map[key] = normalize_attr_any(value);
476 void assign_edge_attrs(EdgeDesc e, std::initializer_list<std::pair<std::string, std::any>> attrs) {
477 auto& edge_attr_map = edge_properties[get_edge_id(e)];
478 for (
const auto& [key, value] : attrs) {
479 edge_attr_map[key] = normalize_attr_any(value);
483 void assign_edge_attr(EdgeDesc e,
const std::pair<std::string, std::any>& attr) {
484 edge_properties[get_edge_id(e)][attr.first] = normalize_attr_any(attr.second);
491 vertex_name_map(boost::get(boost::vertex_name, g)),
492 vertex_index_map(boost::get(boost::vertex_wrapper_index, g)),
493 edge_id_map(boost::get(boost::edge_index, g)),
497 clear_min_cost_flow_state();
508 invalidate_min_cost_flow_state();
509 get_or_create_vertex(
id);
519 for (
const auto& n :
nodes) {
531 auto it_u = id_to_bgl.find(u);
532 auto it_v = id_to_bgl.find(v);
533 if (it_u == id_to_bgl.end() || it_v == id_to_bgl.end())
throw std::runtime_error(
"Node lookup failed: node not found.");
534 auto [e, exists] = boost::edge(it_u->second, it_v->second, g);
535 if (!exists)
throw std::runtime_error(
"Edge lookup failed: edge not found.");
546 bool has_edge(
const NodeID& u,
const NodeID& v)
const {
547 auto it_u = id_to_bgl.find(u);
548 auto it_v = id_to_bgl.find(v);
549 if (it_u == id_to_bgl.end() || it_v == id_to_bgl.end())
return false;
550 auto [e, exists] = boost::edge(it_u->second, it_v->second, g);
557 std::vector<std::size_t>
edge_ids()
const;
559 std::vector<std::size_t>
edge_ids(
const NodeID& u,
const NodeID& v)
const;
563 template <
bool W = Weighted>
576 void add_edge(
const NodeID& u,
const NodeID& v, EdgeWeight w = 1.0) {
577 invalidate_min_cost_flow_state();
578 VertexDesc bu = get_or_create_vertex(u);
579 VertexDesc bv = get_or_create_vertex(v);
581 if constexpr (!Multi) {
582 auto [e, exists] = boost::edge(bu, bv, g);
589 auto [e, added] = boost::add_edge(bu, bv, g);
591 edge_id_map[e] = next_edge_id++;
594 template <
bool W = Weighted>
602 std::size_t add_edge_with_id(
const NodeID& u,
const NodeID& v, EdgeWeight w = 1.0);
604 template <
bool W = Weighted>
615 void add_edge(
const NodeID& u,
const NodeID& v) {
616 invalidate_min_cost_flow_state();
617 VertexDesc bu = get_or_create_vertex(u);
618 VertexDesc bv = get_or_create_vertex(v);
620 if constexpr (!Multi) {
621 auto [e, exists] = boost::edge(bu, bv, g);
627 auto [e, added] = boost::add_edge(bu, bv, g);
629 edge_id_map[e] = next_edge_id++;
632 template <
bool W = Weighted>
640 std::size_t add_edge_with_id(
const NodeID& u,
const NodeID& v);
651 template <
bool W = Weighted>
653 void add_edge(
const NodeID& u,
const NodeID& v, EdgeWeight w,
const EdgeAttrMap& attrs);
662 void add_edge(
const NodeID& u,
const NodeID& v,
const EdgeAttrMap& attrs);
664 template <
bool W = Weighted>
674 void add_edge(
const NodeID& u,
const NodeID& v, EdgeWeight w,
const std::pair<std::string, std::any>& attr);
677 void add_edge(
const NodeID& u,
const NodeID& v,
const std::pair<std::string, std::any>& attr);
679 template <
bool W = Weighted>
689 void add_edge(
const NodeID& u,
const NodeID& v, EdgeWeight w, std::initializer_list<std::pair<std::string, std::any>> attrs);
692 void add_edge(
const NodeID& u,
const NodeID& v, std::initializer_list<std::pair<std::string, std::any>> attrs);
693 template <
bool W = Weighted>
696 void add_edges_from(
const std::vector<std::tuple<NodeID, NodeID, EdgeWeight>>&
edges) {
697 for (
const auto& edge :
edges) {
698 add_edge(std::get<0>(edge), std::get<1>(edge), std::get<2>(edge));
704 for (
const auto& edge :
edges) {
705 add_edge(edge.first, edge.second);
717 invalidate_min_cost_flow_state();
721 node_properties.clear();
722 edge_properties.clear();
724 vertex_name_map = boost::get(boost::vertex_name, g);
725 vertex_index_map = boost::get(boost::vertex_wrapper_index, g);
726 edge_id_map = boost::get(boost::edge_index, g);
740 invalidate_min_cost_flow_state();
741 auto it_u = id_to_bgl.find(u);
742 auto it_v = id_to_bgl.find(v);
743 if (it_u == id_to_bgl.end() || it_v == id_to_bgl.end()) {
744 throw std::runtime_error(
"Node lookup failed: node not found.");
746 auto [e, exists] = boost::edge(it_u->second, it_v->second, g);
748 throw std::runtime_error(
"Edge lookup failed: edge not found.");
750 for (
auto edge_id : collect_edge_ids_between(it_u->second, it_v->second)) {
751 edge_properties.erase(edge_id);
753 boost::remove_edge(it_u->second, it_v->second, g);
773 invalidate_min_cost_flow_state();
774 auto it = id_to_bgl.find(u);
775 if (it == id_to_bgl.end()) {
776 throw std::runtime_error(
"Node lookup failed: node not found.");
778 VertexDesc v = it->second;
780 erase_incident_edge_properties(v);
781 boost::clear_vertex(v, g);
782 boost::remove_vertex(v, g);
784 node_properties.erase(u);
785 rebuild_vertex_maps();
795 auto it = id_to_bgl.find(u);
796 if (it == id_to_bgl.end()) {
797 throw std::runtime_error(
"Node lookup failed: node not found.");
799 std::vector<NodeID> res;
800 for (
auto [e, eend] = boost::out_edges(it->second, g); e != eend; ++e) {
801 res.push_back(node_id_of(boost::target(*e, g)));
818 auto it = id_to_bgl.find(u);
819 if (it == id_to_bgl.end()) {
820 throw std::runtime_error(
"Node lookup failed: node not found.");
823 std::vector<NodeID> res;
824 if constexpr (Directed) {
825 for (
auto [e, eend] = boost::in_edges(it->second, g); e != eend; ++e) {
826 res.push_back(node_id_of(boost::source(*e, g)));
829 for (
auto [e, eend] = boost::out_edges(it->second, g); e != eend; ++e) {
830 res.push_back(node_id_of(boost::target(*e, g)));
838 return id_to_bgl.find(u) != id_to_bgl.end();
848 bool has_node_attr(
const NodeID& u,
const std::string& key)
const;
856 bool has_edge_attr(
const NodeID& u,
const NodeID& v,
const std::string& key)
const;
858 bool has_edge_attr(std::size_t edge_id,
const std::string& key)
const;
860 template <
typename T>
867 T
get_node_attr(
const NodeID& u,
const std::string& key)
const;
869 template <
typename T>
876 T
get_edge_attr(
const NodeID& u,
const NodeID& v,
const std::string& key)
const;
878 template <
typename T>
884 T
get_edge_attr(std::size_t edge_id,
const std::string& key)
const;
886 template <
typename T>
893 std::optional<T>
try_get_node_attr(
const NodeID& u,
const std::string& key)
const;
895 template <
typename T>
903 std::optional<T>
try_get_edge_attr(
const NodeID& u,
const NodeID& v,
const std::string& key)
const;
905 template <
typename T>
907 std::optional<T>
try_get_edge_attr(std::size_t edge_id,
const std::string& key)
const;
920 template <
bool W = Weighted>
929 EdgeWeight get_edge_weight(
const NodeID& u,
const NodeID& v)
const;
931 template <
bool W = Weighted>
934 EdgeWeight get_edge_weight(std::size_t edge_id)
const;
936 template <
bool W = Weighted>
939 void set_edge_weight(std::size_t edge_id, EdgeWeight w);
941 template <
typename T>
948 void set_edge_attr(std::size_t edge_id,
const std::string& key,
const T& value);
957 std::vector<NodeID> res;
958 for (
auto [v, vend] = boost::vertices(g); v != vend; ++v) {
959 res.push_back(node_id_of(*v));
971 if constexpr (Weighted) {
972 std::vector<std::tuple<NodeID, NodeID, EdgeWeight>> res;
973 for (
auto [e, eend] = boost::edges(g); e != eend; ++e) {
974 NodeID source_id = node_id_of(boost::source(*e, g));
975 NodeID target_id = node_id_of(boost::target(*e, g));
976 res.emplace_back(source_id, target_id, weight_map[*e]);
980 std::vector<std::pair<NodeID, NodeID>> res;
981 for (
auto [e, eend] = boost::edges(g); e != eend; ++e) {
982 NodeID source_id = node_id_of(boost::source(*e, g));
983 NodeID target_id = node_id_of(boost::target(*e, g));
984 res.emplace_back(source_id, target_id);
992 std::vector<std::pair<NodeID, NodeID>> res;
993 for (
auto [e, eend] = boost::edges(g); e != eend; ++e) {
994 NodeID source_id = node_id_of(boost::source(*e, g));
995 NodeID target_id = node_id_of(boost::target(*e, g));
996 res.emplace_back(source_id, target_id);
1008 const NodeID&
get_node_id(VertexDesc v)
const {
return node_id_of(v); }
1023 template <
typename T>
1026 if constexpr (Weighted) graph->add_edge(u, v,
static_cast<EdgeWeight
>(1.0));
1027 else graph->add_edge(u, v);
1030 graph->edge_properties[graph->get_edge_id(e)][key] = Graph::make_attr_any(val);
1034 template <
typename T>
1035 operator T()
const {
1036 return graph->template get_edge_attr<T>(u, v, key);
1044 EdgeProxy(
Graph* g, NodeID u, NodeID v) : graph(g), u(u), v(v) {}
1047 template <
bool W = Weighted>
1050 graph->add_edge(u, v, w);
1054 template <
bool W = Weighted>
1056 operator EdgeWeight()
const {
1057 return graph->get_edge_weight(u, v);
1060 EdgeAttrProxy operator[](
const std::string& key) {
1061 return {graph, u, v, key};
1064 EdgeAttrProxy operator[](
const char* key) {
1065 return {graph, u, v, std::string(key)};
1078 template <
typename T>
1081 graph->node_properties[u][key] = Graph::make_attr_any(val);
1085 template <
typename T>
1086 operator T()
const {
1087 return graph->template get_node_attr<T>(u, key);
1109 return {graph, u, key};
1113 return {graph, u, std::string(key)};
1156 auto bfs_edges(
const NodeID& start)
const;
1167 auto bfs_tree(
const NodeID& start)
const;
1191 template <
typename Visitor>
1207 template <
typename OnVertex,
typename OnTreeEdge>
1208 void bfs_visit(
const NodeID& start, OnVertex&& on_vertex, OnTreeEdge&& on_tree_edge)
const;
1217 auto dfs_edges(
const NodeID& start)
const;
1228 auto dfs_tree(
const NodeID& start)
const;
1263 template <
typename Visitor>
1279 template <
typename OnTreeEdge,
typename OnBackEdge>
1280 void dfs_visit(
const NodeID& start, OnTreeEdge&& on_tree_edge, OnBackEdge&& on_back_edge)
const;
1290 auto shortest_path(
const NodeID& source_id,
const NodeID& target_id)
const;
1303 auto shortest_path(
const NodeID& source_id,
const NodeID& target_id,
const std::string& weight)
const;
1325 double shortest_path_length(
const NodeID& source_id,
const NodeID& target_id,
const std::string& weight)
const;
1335 template <
bool W = Weighted>
1337 auto dijkstra_path(
const NodeID& source_id,
const NodeID& target_id)
const;
1351 template <
bool W = Weighted>
1353 auto dijkstra_path(
const NodeID& source_id,
const NodeID& target_id,
const std::string& weight)
const;
1363 template <
bool W = Weighted>
1374 template <
bool W = Weighted>
1386 template <
bool W = Weighted>
1402 template <
bool W = Weighted>
1404 auto dijkstra_path_length(
const NodeID& source_id,
const NodeID& target_id,
const std::string& weight)
const;
1414 template <
bool W = Weighted>
1426 template <
bool W = Weighted>
1439 template <
bool W = Weighted>
1441 auto bellman_ford_path(
const NodeID& source_id,
const NodeID& target_id,
const std::string& weight)
const;
1451 template <
bool W = Weighted>
1464 template <
bool W = Weighted>
1476 template <
bool W = Weighted>
1490 template <
bool W = Weighted>
1504 template <
bool W = Weighted>
1536 template <
bool W = Weighted>
1547 template <
bool W = Weighted>
1558 template <
bool W = Weighted>
1569 template <
bool W = Weighted>
1583 auto edmonds_karp_maximum_flow(
const NodeID& source_id,
const NodeID& target_id,
const std::string& capacity_attr =
"capacity")
const;
1605 auto maximum_flow(
const NodeID& source_id,
const NodeID& target_id,
const std::string& capacity_attr =
"capacity")
const;
1616 auto minimum_cut(
const NodeID& source_id,
const NodeID& target_id,
const std::string& capacity_attr =
"capacity")
const;
1628 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;
1630 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;
1641 auto cycle_canceling(
const std::string& weight_attr =
"weight")
const;
1677 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;
1719 void invalidate_min_cost_flow_state()
const {
1721 static_cast<const void*
>(
this)
1725 void clear_min_cost_flow_state()
const {
1726 detail::MinCostFlowCacheHooks<Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>>
::clear(
1727 static_cast<const void*
>(
this)
1732template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
1734 return static_cast<int>(boost::num_vertices(g));
1738template <
typename GraphWrapper>
1740[[deprecated(
"Use G.num_vertices() instead.")]]
1742 return G.num_vertices();
Definition graph.hpp:1040
Definition graph.hpp:1102
Definition graph.hpp:1091
Graph wrapper around Boost Graph Library with Python-inspired helpers.
Definition graph.hpp:272
const IdMap & get_id_to_bgl_map() const
Returns the maintained node-ID-to-vertex translation table.
Definition graph.hpp:1006
auto bellman_ford_path(const NodeID &source_id, const NodeID &target_id) const
Computes a shortest path using Bellman-Ford and built-in weights.
Definition shortest_paths.hpp:647
auto minimum_spanning_tree() const
Convenience alias for kruskal_minimum_spanning_tree().
Definition spanning_tree.hpp:112
double get_edge_numeric_attr(const NodeID &u, const NodeID &v, const std::string &key) const
Reads an endpoint-selected edge attribute as a numeric value.
Definition attributes.hpp:219
void add_nodes_from(const std::vector< NodeID > &nodes)
Adds a batch of nodes from a vector of node IDs.
Definition graph.hpp:518
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:377
std::optional< T > try_get_node_attr(const NodeID &u, const std::string &key) const
Attempts to read a typed node attribute without throwing.
Definition attributes.hpp:182
void add_edges_from(const std::vector< std::pair< NodeID, NodeID > > &edges)
Adds a batch of unweighted edges from (u, v) pairs.
Definition graph.hpp:703
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:671
auto dijkstra_path(const NodeID &source_id, const NodeID &target_id) const
Computes the shortest path using the built-in edge-weight property.
Definition shortest_paths.hpp:400
auto bellman_ford_shortest_paths(const NodeID &source_id) const
Returns distances and predecessors for all nodes using Bellman-Ford.
Definition shortest_paths.hpp:683
auto dijkstra_path_length(const NodeID &source_id) const
Returns built-in-weight shortest-path distances from a source node.
Definition shortest_paths.hpp:480
auto dfs_predecessors(const NodeID &start) const
Returns the DFS predecessor assigned to each discovered node.
Definition traversal.hpp:466
bool has_node_attr(const NodeID &u, const std::string &key) const
Returns whether a node has the named attribute.
Definition attributes.hpp:113
auto dijkstra_shortest_paths(const NodeID &source_id) const
Returns distances and predecessors for all nodes reachable from a source.
Definition shortest_paths.hpp:446
auto bfs_tree(const NodeID &start) const
Materializes the breadth-first-search tree rooted at start.
Definition traversal.hpp:371
void set_edge_attr(std::size_t edge_id, const std::string &key, const T &value)
Stores a typed attribute on an edge identified by edge ID.
Definition multigraph.hpp:186
EdgeDesc get_edge_desc(const NodeID &u, const NodeID &v) const
Returns the underlying Boost edge descriptor for an existing edge.
Definition graph.hpp:530
void remove_edge(const NodeID &u, const NodeID &v)
Removes all edges between two endpoints.
Definition graph.hpp:739
std::vector< NodeID > neighbors(const NodeID &u) const
Returns the outgoing neighbors of a node.
Definition graph.hpp:794
auto num_vertices() const
Returns the number of vertices currently stored in the graph.
Definition graph.hpp:1733
std::pair< NodeID, NodeID > get_edge_endpoints(std::size_t edge_id) const
Returns the endpoints of an edge identified by its wrapper-managed ID.
Definition multigraph.hpp:40
auto strongly_connected_component_roots() const
Returns one representative root node for each strong component.
Definition components.hpp:233
T get_node_attr(const NodeID &u, const std::string &key) const
Reads a typed node attribute.
Definition attributes.hpp:145
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:732
std::vector< NodeID > predecessors(const NodeID &u) const
Returns predecessor nodes for directed graphs.
Definition graph.hpp:817
void bfs_visit(const NodeID &start, OnVertex &&on_vertex, OnTreeEdge &&on_tree_edge) const
Runs breadth-first search with lightweight callback hooks.
Definition traversal.hpp:416
auto betweenness_centrality() const
Computes normalized betweenness centrality for every node.
Definition centrality.hpp:118
auto pagerank() const
Computes PageRank scores for every node.
Definition centrality.hpp:46
std::vector< NodeID > nodes() const
Returns all node IDs currently stored in the graph.
Definition graph.hpp:956
auto prim_minimum_spanning_tree(const NodeID &root_id) const
Returns the parent map produced by Prim's minimum-spanning-tree algorithm.
Definition spanning_tree.hpp:90
bool has_edge_attr(const NodeID &u, const NodeID &v, const std::string &key) const
Returns whether an endpoint-selected edge has the named attribute.
Definition attributes.hpp:122
std::optional< T > try_get_edge_attr(const NodeID &u, const NodeID &v, const std::string &key) const
Attempts to read a typed edge attribute selected by endpoints.
Definition attributes.hpp:199
void dfs_visit(const NodeID &start, OnTreeEdge &&on_tree_edge, OnBackEdge &&on_back_edge) const
Runs depth-first search with lightweight callback hooks.
Definition traversal.hpp:507
auto dfs_successors(const NodeID &start) const
Groups DFS tree children by their discovered parent.
Definition traversal.hpp:476
auto bfs_edges(const NodeID &start) const
Returns the tree edges discovered by breadth-first search.
Definition traversal.hpp:356
T get_edge_attr(const NodeID &u, const NodeID &v, const std::string &key) const
Reads a typed edge attribute selected by endpoints.
Definition attributes.hpp:163
bool has_node(const NodeID &u) const
Returns whether the graph already contains the given node ID.
Definition graph.hpp:837
const std::vector< NodeID > & get_bgl_to_id_map() const
Returns the maintained vertex-index-to-node-ID translation table.
Definition graph.hpp:1004
auto edges() const
Returns the public edge list.
Definition graph.hpp:970
void depth_first_search(const NodeID &start, Visitor &visitor) const
Runs depth-first search with an object-style visitor.
Definition traversal.hpp:491
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:727
void add_node(const NodeID &id)
Ensures that a node with the given ID exists in the graph.
Definition graph.hpp:507
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:482
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:479
auto topological_sort() const
Returns a topological ordering for a directed acyclic graph.
Definition topological_sort.hpp:29
auto dag_shortest_paths(const NodeID &source_id) const
Returns shortest-path distances in a directed acyclic graph.
Definition shortest_paths.hpp:745
const GraphType & get_impl() const
Exposes the underlying Boost graph for advanced integrations.
Definition graph.hpp:1002
auto strongly_connected_component_map() const
Alias for strong_component_map().
Definition components.hpp:230
void clear()
Clears the entire graph and all wrapper-managed metadata.
Definition graph.hpp:716
std::size_t get_vertex_index(VertexDesc v) const
Returns the wrapper-maintained dense vertex index used by algorithms.
Definition graph.hpp:1010
void breadth_first_search(const NodeID &start, Visitor &visitor) const
Runs breadth-first search with an object-style visitor.
Definition traversal.hpp:401
auto connected_component_groups() const
Groups each connected component as a vector of node IDs.
Definition components.hpp:136
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:610
auto dfs_edges(const NodeID &start) const
Returns the tree edges discovered by depth-first search.
Definition traversal.hpp:430
auto bfs_successors(const NodeID &start) const
Groups BFS tree children by their discovered parent.
Definition traversal.hpp:386
void remove_node(const NodeID &u)
Removes a node and all of its incident edges.
Definition graph.hpp:772
auto cycle_canceling(const std::string &weight_attr="weight") const
Runs cycle canceling on the previously cached residual network.
Definition flow.hpp:649
const NodeID & get_node_id(VertexDesc v) const
Returns the wrapper-side node ID associated with a Boost vertex descriptor.
Definition graph.hpp:1008
auto connected_component_map() const
Returns the connected-component index assigned to each node.
Definition components.hpp:224
auto strong_component_map() const
Returns the component index assigned to each node in a directed graph.
Definition components.hpp:190
auto bellman_ford_path_length(const NodeID &source_id, const NodeID &target_id) const
Returns the Bellman-Ford shortest-path length with built-in weights.
Definition shortest_paths.hpp:727
std::vector< std::size_t > edge_ids() const
Returns all wrapper-managed edge IDs currently present in the graph.
Definition multigraph.hpp:21
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:549
bool has_edge_id(std::size_t edge_id) const
Returns whether an edge with the given wrapper-managed ID exists.
Definition multigraph.hpp:16
auto degree_centrality() const
Computes normalized degree centrality for every node.
Definition centrality.hpp:16
std::vector< std::pair< NodeID, NodeID > > edge_pairs() const
Returns all edges as endpoint pairs, ignoring built-in weights.
Definition graph.hpp:991
auto strong_components() const
Returns the number of strongly connected components in a directed graph.
Definition components.hpp:206
auto dfs_tree(const NodeID &start) const
Materializes the depth-first-search tree rooted at start.
Definition traversal.hpp:451
bool has_edge(const NodeID &u, const NodeID &v) const
Returns whether at least one edge exists between two endpoints.
Definition graph.hpp:546
auto shortest_path(const NodeID &source_id, const NodeID &target_id) const
Computes an unweighted shortest path between two nodes.
Definition shortest_paths.hpp:300
auto kruskal_minimum_spanning_tree() const
Returns the edges selected by Kruskal's minimum-spanning-tree algorithm.
Definition spanning_tree.hpp:78
std::vector< NodeID > successors(const NodeID &u) const
Alias for neighbors(), mainly to mirror directed-graph terminology.
Definition graph.hpp:807
auto connected_components() const
Returns the number of connected components in an undirected graph.
Definition components.hpp:155
auto floyd_warshall_all_pairs_shortest_paths_map() const
Returns all-pairs shortest-path distances keyed by node IDs.
Definition shortest_paths.hpp:817
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:428
auto floyd_warshall_all_pairs_shortest_paths() const
Returns all-pairs shortest-path distances as a dense matrix.
Definition shortest_paths.hpp:781
NodeAttrBaseProxy node(const NodeID &u)
Returns the proxy used for G.node(u)[key] node-attribute syntax.
Definition graph.hpp:1142
NodeProxy operator[](const NodeID &u)
Returns the proxy used for G[u][v] edge-access syntax.
Definition graph.hpp:1130
auto strongly_connected_component_groups() const
Groups each strongly connected component as a vector of node IDs.
Definition components.hpp:171
double shortest_path_length(const NodeID &source_id, const NodeID &target_id) const
Returns the length of an unweighted shortest path.
Definition shortest_paths.hpp:374
auto strongly_connected_components() const
Alias for strongly_connected_component_groups().
Definition components.hpp:227
indexed_lookup_map()=default
Default-constructs an empty ordered lookup map.
Minimal visitor interface for wrapper-level traversal callbacks.
Definition traversal.hpp:26
auto num_vertices(const GraphWrapper &G)
Deprecated free-function alias for num_vertices().
Definition graph.hpp:1741
Definition graph.hpp:1013
EdgeAttrProxy & operator=(const T &val)
Sets attribute key on edge (u,v), creating the edge if it does not exist.
Definition graph.hpp:1024
Definition graph.hpp:1069
NodeAttrProxy & operator=(const T &val)
Sets attribute key on node u, creating the node if it does not exist.
Definition graph.hpp:1079