15template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
16static void throw_if_multigraph_attr_add_is_ambiguous() {
17 if constexpr (Multi) {
18 throw std::runtime_error(
19 "Multigraph endpoint-based add_edge(..., attrs) is ambiguous. "
20 "Use add_edge_with_id(...) and then set_edge_attr(edge_id, ...)."
25template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
32 const EdgeAttrMap& attrs
34 throw_if_multigraph_attr_add_is_ambiguous<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>();
36 assign_edge_attrs(get_edge_desc(u, v), attrs);
39template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
43 const EdgeAttrMap& attrs
45 throw_if_multigraph_attr_add_is_ambiguous<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>();
46 if constexpr (Weighted) {
47 add_edge(u, v,
static_cast<EdgeWeight
>(1.0), attrs);
50 assign_edge_attrs(get_edge_desc(u, v), attrs);
54template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
61 const std::pair<std::string, std::any>& attr
63 throw_if_multigraph_attr_add_is_ambiguous<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>();
65 assign_edge_attr(get_edge_desc(u, v), attr);
68template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
72 const std::pair<std::string, std::any>& attr
74 throw_if_multigraph_attr_add_is_ambiguous<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>();
75 if constexpr (Weighted) {
76 add_edge(u, v,
static_cast<EdgeWeight
>(1.0), attr);
79 assign_edge_attr(get_edge_desc(u, v), attr);
83template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
90 std::initializer_list<std::pair<std::string, std::any>> attrs
92 throw_if_multigraph_attr_add_is_ambiguous<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>();
94 assign_edge_attrs(get_edge_desc(u, v), attrs);
97template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
101 std::initializer_list<std::pair<std::string, std::any>> attrs
103 throw_if_multigraph_attr_add_is_ambiguous<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>();
104 if constexpr (Weighted) {
105 add_edge(u, v,
static_cast<EdgeWeight
>(1.0), attrs);
108 assign_edge_attrs(get_edge_desc(u, v), attrs);
112template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
114 auto node_it = node_properties.find(u);
115 if (node_it == node_properties.end()) {
118 return node_it->second.find(key) != node_it->second.end();
121template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
123 if (!has_edge(u, v)) {
126 auto e = get_edge_desc(u, v);
127 auto edge_it = edge_properties.find(get_edge_id(e));
128 if (edge_it == edge_properties.end()) {
131 return edge_it->second.find(key) != edge_it->second.end();
134template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
136 auto edge_it = edge_properties.find(edge_id);
137 if (edge_it == edge_properties.end()) {
140 return edge_it->second.find(key) != edge_it->second.end();
143template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
146 auto node_it = node_properties.find(u);
147 if (node_it == node_properties.end()) {
148 throw std::runtime_error(
"Node attribute lookup failed: node has no attributes.");
150 auto attr_it = node_it->second.find(key);
151 if (attr_it == node_it->second.end()) {
152 throw std::runtime_error(
"Node attribute lookup failed: key not found.");
155 return std::any_cast<T>(attr_it->second);
156 }
catch (
const std::bad_any_cast&) {
157 throw std::runtime_error(
"Node attribute lookup failed: stored type does not match requested type.");
161template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
164 auto e = get_edge_desc(u, v);
165 auto edge_it = edge_properties.find(get_edge_id(e));
166 if (edge_it == edge_properties.end()) {
167 throw std::runtime_error(
"Edge attribute lookup failed: edge has no attributes.");
169 auto attr_it = edge_it->second.find(key);
170 if (attr_it == edge_it->second.end()) {
171 throw std::runtime_error(
"Edge attribute lookup failed: key not found.");
174 return std::any_cast<T>(attr_it->second);
175 }
catch (
const std::bad_any_cast&) {
176 throw std::runtime_error(
"Edge attribute lookup failed: stored type does not match requested type.");
180template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
183 auto node_it = node_properties.find(u);
184 if (node_it == node_properties.end()) {
187 auto attr_it = node_it->second.find(key);
188 if (attr_it == node_it->second.end()) {
191 if (
const auto* value = std::any_cast<T>(&(attr_it->second))) {
197template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
200 if (!has_edge(u, v)) {
203 auto e = get_edge_desc(u, v);
204 auto edge_it = edge_properties.find(get_edge_id(e));
205 if (edge_it == edge_properties.end()) {
208 auto attr_it = edge_it->second.find(key);
209 if (attr_it == edge_it->second.end()) {
212 if (
const auto* value = std::any_cast<T>(&(attr_it->second))) {
218template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
220 if (key ==
"weight") {
221 if constexpr (Weighted) {
222 return static_cast<double>(get_edge_weight(u, v));
224 throw std::runtime_error(
"Edge attribute lookup failed: graph has no built-in edge weight.");
228 auto e = get_edge_desc(u, v);
229 auto edge_it = edge_properties.find(get_edge_id(e));
230 if (edge_it == edge_properties.end()) {
231 throw std::runtime_error(
"Edge attribute lookup failed: edge has no attributes.");
233 auto attr_it = edge_it->second.find(key);
234 if (attr_it == edge_it->second.end()) {
235 throw std::runtime_error(
"Edge attribute lookup failed: key not found.");
238 const auto& value = attr_it->second;
239 if (
const auto* vptr = std::any_cast<int>(&value))
return static_cast<double>(*vptr);
240 if (
const auto* vptr = std::any_cast<long>(&value))
return static_cast<double>(*vptr);
241 if (
const auto* vptr = std::any_cast<long long>(&value))
return static_cast<double>(*vptr);
242 if (
const auto* vptr = std::any_cast<float>(&value))
return static_cast<double>(*vptr);
243 if (
const auto* vptr = std::any_cast<double>(&value))
return *vptr;
245 throw std::runtime_error(
"Edge attribute lookup failed: stored value is not numeric.");
248template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
252 auto it_u = id_to_bgl.find(u);
253 auto it_v = id_to_bgl.find(v);
254 if (it_u == id_to_bgl.end() || it_v == id_to_bgl.end())
throw std::runtime_error(
"Node lookup failed: node not found.");
255 auto [e, exists] = boost::edge(it_u->second, it_v->second, g);
256 if (!exists)
throw std::runtime_error(
"Edge lookup failed: edge not found.");
257 return weight_map[e];
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
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
bool has_node_attr(const NodeID &u, const std::string &key) const
Returns whether a node has the named attribute.
Definition attributes.hpp:113
T get_node_attr(const NodeID &u, const std::string &key) const
Reads a typed node attribute.
Definition attributes.hpp:145
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
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
Core graph wrapper, proxy surface, and public alias presets.