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();
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));
29template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
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()) {
36 return collect_edge_ids_between(it_u->second, it_v->second);
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);
43 node_id_of(boost::source(e, g)),
44 node_id_of(boost::target(e, g))
48template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
52 invalidate_min_cost_flow_state();
53 VertexDesc bu = get_or_create_vertex(u);
54 VertexDesc bv = get_or_create_vertex(v);
56 if constexpr (!Multi) {
57 auto [e, exists] = boost::edge(bu, bv, g);
60 return get_edge_id(e);
64 auto [e, added] = boost::add_edge(bu, bv, g);
67 edge_id_map[e] = next_edge_id++;
68 return get_edge_id(e);
71template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
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);
79 if constexpr (!Multi) {
80 auto [e, exists] = boost::edge(bu, bv, g);
82 return get_edge_id(e);
86 auto [e, added] = boost::add_edge(bu, bv, g);
88 edge_id_map[e] = next_edge_id++;
89 return get_edge_id(e);
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.");
99 edge_properties.erase(edge_id);
100 boost::remove_edge(*edge_desc, g);
103template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
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.");
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.");
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.");
121template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
124 auto edge_it = edge_properties.find(edge_id);
125 if (edge_it == edge_properties.end()) {
128 auto attr_it = edge_it->second.find(key);
129 if (attr_it == edge_it->second.end()) {
132 if (
const auto* value = std::any_cast<T>(&(attr_it->second))) {
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));
144 throw std::runtime_error(
"Edge attribute lookup failed: graph has no built-in edge weight.");
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.");
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.");
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;
164 throw std::runtime_error(
"Edge attribute lookup failed: stored value is not numeric.");
167template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
171 auto e = get_edge_desc_by_id(edge_id);
172 return weight_map[e];
175template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
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);
184template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
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);
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