16template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
17static void throw_if_multigraph_attr_add_is_ambiguous() {
18 if constexpr (Multi) {
19 throw std::runtime_error(
20 "Multigraph endpoint-based add_edge(..., attrs) is ambiguous. "
21 "Use add_edge_with_id(...) and then set_edge_attr(edge_id, ...)."
26template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
33 const EdgeAttrMap& attrs
35 throw_if_multigraph_attr_add_is_ambiguous<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>();
37 assign_edge_attrs(get_edge_desc(u, v), attrs);
40template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
44 const EdgeAttrMap& attrs
46 throw_if_multigraph_attr_add_is_ambiguous<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>();
47 if constexpr (Weighted) {
48 add_edge(u, v,
static_cast<EdgeWeight
>(1.0), attrs);
51 assign_edge_attrs(get_edge_desc(u, v), attrs);
55template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
62 const std::pair<std::string, std::any>& attr
64 throw_if_multigraph_attr_add_is_ambiguous<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>();
66 assign_edge_attr(get_edge_desc(u, v), attr);
69template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
73 const std::pair<std::string, std::any>& attr
75 throw_if_multigraph_attr_add_is_ambiguous<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>();
76 if constexpr (Weighted) {
77 add_edge(u, v,
static_cast<EdgeWeight
>(1.0), attr);
80 assign_edge_attr(get_edge_desc(u, v), attr);
84template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
91 std::initializer_list<std::pair<std::string, std::any>> attrs
93 throw_if_multigraph_attr_add_is_ambiguous<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>();
95 assign_edge_attrs(get_edge_desc(u, v), attrs);
98template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
102 std::initializer_list<std::pair<std::string, std::any>> attrs
104 throw_if_multigraph_attr_add_is_ambiguous<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>();
105 if constexpr (Weighted) {
106 add_edge(u, v,
static_cast<EdgeWeight
>(1.0), attrs);
109 assign_edge_attrs(get_edge_desc(u, v), attrs);
113template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
115 auto node_it = node_properties.find(u);
116 if (node_it == node_properties.end()) {
119 return node_it->second.find(key) != node_it->second.end();
122template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
124 if (!has_edge(u, v)) {
127 auto e = get_edge_desc(u, v);
128 auto edge_it = edge_properties.find(get_edge_id(e));
129 if (edge_it == edge_properties.end()) {
132 return edge_it->second.find(key) != edge_it->second.end();
135template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
137 auto edge_it = edge_properties.find(edge_id);
138 if (edge_it == edge_properties.end()) {
141 return edge_it->second.find(key) != edge_it->second.end();
144template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
147 auto node_it = node_properties.find(u);
148 if (node_it == node_properties.end()) {
149 throw std::runtime_error(
"Node attribute lookup failed: node has no attributes.");
151 auto attr_it = node_it->second.find(key);
152 if (attr_it == node_it->second.end()) {
153 throw std::runtime_error(
"Node attribute lookup failed: key not found.");
156 return std::any_cast<T>(attr_it->second);
157 }
catch (
const std::bad_any_cast&) {
158 throw std::runtime_error(
"Node attribute lookup failed: stored type does not match requested type.");
162template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
165 auto e = get_edge_desc(u, v);
166 auto edge_it = edge_properties.find(get_edge_id(e));
167 if (edge_it == edge_properties.end()) {
168 throw std::runtime_error(
"Edge attribute lookup failed: edge has no attributes.");
170 auto attr_it = edge_it->second.find(key);
171 if (attr_it == edge_it->second.end()) {
172 throw std::runtime_error(
"Edge attribute lookup failed: key not found.");
175 return std::any_cast<T>(attr_it->second);
176 }
catch (
const std::bad_any_cast&) {
177 throw std::runtime_error(
"Edge attribute lookup failed: stored type does not match requested type.");
181template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
184 auto node_it = node_properties.find(u);
185 if (node_it == node_properties.end()) {
188 auto attr_it = node_it->second.find(key);
189 if (attr_it == node_it->second.end()) {
192 if (
const auto* value = std::any_cast<T>(&(attr_it->second))) {
198template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
201 if (!has_edge(u, v)) {
204 auto e = get_edge_desc(u, v);
205 auto edge_it = edge_properties.find(get_edge_id(e));
206 if (edge_it == edge_properties.end()) {
209 auto attr_it = edge_it->second.find(key);
210 if (attr_it == edge_it->second.end()) {
213 if (
const auto* value = std::any_cast<T>(&(attr_it->second))) {
219template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
221 if (key ==
"weight") {
222 if constexpr (Weighted) {
223 return static_cast<double>(get_edge_weight(u, v));
225 throw std::runtime_error(
"Edge attribute lookup failed: graph has no built-in edge weight.");
229 auto e = get_edge_desc(u, v);
230 auto edge_it = edge_properties.find(get_edge_id(e));
231 if (edge_it == edge_properties.end()) {
232 throw std::runtime_error(
"Edge attribute lookup failed: edge has no attributes.");
234 auto attr_it = edge_it->second.find(key);
235 if (attr_it == edge_it->second.end()) {
236 throw std::runtime_error(
"Edge attribute lookup failed: key not found.");
239 if (
auto numeric_value = detail::try_numeric_any_cast(attr_it->second)) {
240 return *numeric_value;
243 throw std::runtime_error(
"Edge attribute lookup failed: stored value is not numeric.");
246template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
250 auto it_u = id_to_bgl.find(u);
251 auto it_v = id_to_bgl.find(v);
252 if (it_u == id_to_bgl.end() || it_v == id_to_bgl.end())
throw std::runtime_error(
"Node lookup failed: node not found.");
253 auto [e, exists] = boost::edge(it_u->second, it_v->second, g);
254 if (!exists)
throw std::runtime_error(
"Edge lookup failed: edge not found.");
255 return weight_map[e];
Graph wrapper around Boost Graph Library with Python-inspired helpers.
Definition graph.hpp:288
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:220
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:183
bool has_node_attr(const NodeID &u, const std::string &key) const
Returns whether a node has the named attribute.
Definition attributes.hpp:114
T get_node_attr(const NodeID &u, const std::string &key) const
Reads a typed node attribute.
Definition attributes.hpp:146
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:123
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:200
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:164
Core graph wrapper, proxy surface, and public alias presets.
Shared numeric conversion helpers for attribute-backed APIs.