nxpp
Header-only graph utilities on top of Boost Graph Library
Loading...
Searching...
No Matches
multigraph.hpp
Go to the documentation of this file.
1#pragma once
2
11#include "attributes.hpp"
12
13namespace nxpp {
14
15template <typename NodeID, typename EdgeWeight, bool Directed, bool Multi, bool Weighted, typename OutEdgeSelector, typename VertexSelector>
17 return try_find_edge_desc_by_id(edge_id).has_value();
18}
19
20template <typename NodeID, typename EdgeWeight, bool Directed, bool Multi, bool Weighted, typename OutEdgeSelector, typename VertexSelector>
22 std::vector<std::size_t> ids;
23 for (auto [e, eend] = boost::edges(g); e != eend; ++e) {
24 ids.push_back(get_edge_id(*e));
25 }
26 return ids;
27}
28
29template <typename NodeID, typename EdgeWeight, bool Directed, bool Multi, bool Weighted, typename OutEdgeSelector, typename VertexSelector>
30std::vector<std::size_t> Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>::edge_ids(const NodeID& u, const NodeID& v) const {
31 auto it_u = id_to_bgl.find(u);
32 auto it_v = id_to_bgl.find(v);
33 if (it_u == id_to_bgl.end() || it_v == id_to_bgl.end()) {
34 return {};
35 }
36 return collect_edge_ids_between(it_u->second, it_v->second);
37}
38
39template <typename NodeID, typename EdgeWeight, bool Directed, bool Multi, bool Weighted, typename OutEdgeSelector, typename VertexSelector>
41 auto e = get_edge_desc_by_id(edge_id);
42 return {
43 node_id_of(boost::source(e, g)),
44 node_id_of(boost::target(e, g))
45 };
46}
47
48template <typename NodeID, typename EdgeWeight, bool Directed, bool Multi, bool Weighted, typename OutEdgeSelector, typename VertexSelector>
49template <bool W>
50requires(W)
52 invalidate_min_cost_flow_state();
53 VertexDesc bu = get_or_create_vertex(u);
54 VertexDesc bv = get_or_create_vertex(v);
55
56 if constexpr (!Multi) {
57 auto [e, exists] = boost::edge(bu, bv, g);
58 if (exists) {
59 weight_map[e] = w;
60 return get_edge_id(e);
61 }
62 }
63
64 auto [e, added] = boost::add_edge(bu, bv, g);
65 (void)added;
66 weight_map[e] = w;
67 edge_id_map[e] = next_edge_id++;
68 return get_edge_id(e);
69}
70
71template <typename NodeID, typename EdgeWeight, bool Directed, bool Multi, bool Weighted, typename OutEdgeSelector, typename VertexSelector>
72template <bool W>
73requires(!W)
74std::size_t Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>::add_edge_with_id(const NodeID& u, const NodeID& v) {
75 invalidate_min_cost_flow_state();
76 VertexDesc bu = get_or_create_vertex(u);
77 VertexDesc bv = get_or_create_vertex(v);
78
79 if constexpr (!Multi) {
80 auto [e, exists] = boost::edge(bu, bv, g);
81 if (exists) {
82 return get_edge_id(e);
83 }
84 }
85
86 auto [e, added] = boost::add_edge(bu, bv, g);
87 (void)added;
88 edge_id_map[e] = next_edge_id++;
89 return get_edge_id(e);
90}
91
92template <typename NodeID, typename EdgeWeight, bool Directed, bool Multi, bool Weighted, typename OutEdgeSelector, typename VertexSelector>
94 invalidate_min_cost_flow_state();
95 auto edge_desc = try_find_edge_desc_by_id(edge_id);
96 if (!edge_desc.has_value()) {
97 throw std::runtime_error("Edge lookup failed: edge not found.");
98 }
99 edge_properties.erase(edge_id);
100 boost::remove_edge(*edge_desc, g);
101}
102
103template <typename NodeID, typename EdgeWeight, bool Directed, bool Multi, bool Weighted, typename OutEdgeSelector, typename VertexSelector>
104template <typename T>
106 auto edge_it = edge_properties.find(edge_id);
107 if (edge_it == edge_properties.end()) {
108 throw std::runtime_error("Edge attribute lookup failed: edge has no attributes.");
109 }
110 auto attr_it = edge_it->second.find(key);
111 if (attr_it == edge_it->second.end()) {
112 throw std::runtime_error("Edge attribute lookup failed: key not found.");
113 }
114 try {
115 return std::any_cast<T>(attr_it->second);
116 } catch (const std::bad_any_cast&) {
117 throw std::runtime_error("Edge attribute lookup failed: stored type does not match requested type.");
118 }
119}
120
121template <typename NodeID, typename EdgeWeight, bool Directed, bool Multi, bool Weighted, typename OutEdgeSelector, typename VertexSelector>
122template <typename T>
124 auto edge_it = edge_properties.find(edge_id);
125 if (edge_it == edge_properties.end()) {
126 return std::nullopt;
127 }
128 auto attr_it = edge_it->second.find(key);
129 if (attr_it == edge_it->second.end()) {
130 return std::nullopt;
131 }
132 if (const auto* value = std::any_cast<T>(&(attr_it->second))) {
133 return *value;
134 }
135 return std::nullopt;
136}
137
138template <typename NodeID, typename EdgeWeight, bool Directed, bool Multi, bool Weighted, typename OutEdgeSelector, typename VertexSelector>
140 if (key == "weight") {
141 if constexpr (Weighted) {
142 return static_cast<double>(get_edge_weight(edge_id));
143 } else {
144 throw std::runtime_error("Edge attribute lookup failed: graph has no built-in edge weight.");
145 }
146 }
147
148 auto edge_it = edge_properties.find(edge_id);
149 if (edge_it == edge_properties.end()) {
150 throw std::runtime_error("Edge attribute lookup failed: edge has no attributes.");
151 }
152 auto attr_it = edge_it->second.find(key);
153 if (attr_it == edge_it->second.end()) {
154 throw std::runtime_error("Edge attribute lookup failed: key not found.");
155 }
156
157 const auto& value = attr_it->second;
158 if (const auto* vptr = std::any_cast<int>(&value)) return static_cast<double>(*vptr);
159 if (const auto* vptr = std::any_cast<long>(&value)) return static_cast<double>(*vptr);
160 if (const auto* vptr = std::any_cast<long long>(&value)) return static_cast<double>(*vptr);
161 if (const auto* vptr = std::any_cast<float>(&value)) return static_cast<double>(*vptr);
162 if (const auto* vptr = std::any_cast<double>(&value)) return *vptr;
163
164 throw std::runtime_error("Edge attribute lookup failed: stored value is not numeric.");
165}
166
167template <typename NodeID, typename EdgeWeight, bool Directed, bool Multi, bool Weighted, typename OutEdgeSelector, typename VertexSelector>
168template <bool W>
169requires(W)
171 auto e = get_edge_desc_by_id(edge_id);
172 return weight_map[e];
173}
174
175template <typename NodeID, typename EdgeWeight, bool Directed, bool Multi, bool Weighted, typename OutEdgeSelector, typename VertexSelector>
176template <bool W>
177requires(W)
178void Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>::set_edge_weight(std::size_t edge_id, EdgeWeight w) {
179 invalidate_min_cost_flow_state();
180 auto e = get_edge_desc_by_id(edge_id);
181 weight_map[e] = w;
182}
183
184template <typename NodeID, typename EdgeWeight, bool Directed, bool Multi, bool Weighted, typename OutEdgeSelector, typename VertexSelector>
185template <typename T>
187 invalidate_min_cost_flow_state();
188 (void)get_edge_desc_by_id(edge_id);
189 edge_properties[edge_id][key] = make_attr_any(value);
190}
191
192} // namespace nxpp
Attribute-bearing edge insertion helpers and attribute-oriented graph method definitions.
Graph wrapper around Boost Graph Library with Python-inspired helpers.
Definition graph.hpp:272
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 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
void remove_edge(const NodeID &u, const NodeID &v)
Removes all edges between two endpoints.
Definition graph.hpp:739
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
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
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
std::vector< std::size_t > edge_ids() const
Returns all wrapper-managed edge IDs currently present in the graph.
Definition multigraph.hpp:21
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