XNetwork 1.7.5; VERSION ${PROJECT_VERSION}
Loading...
Searching...
No Matches
graph.hpp
Go to the documentation of this file.
1
9#pragma once
10
11#include <cassert>
12#include <cstdint>
13#include <py2cpp/py2cpp.hpp>
14#include <type_traits>
15#include <vector>
16#include <xnetwork/classes/coreviews.hpp> // import AtlasView, AdjacencyView
17#include <xnetwork/classes/reportviews.hpp> // import NodeView, EdgeView, DegreeView
18
20template <typename T> using Value_type = typename T::value_type;
21
22namespace xnetwork {
23
39 // struct object : py::dict<const char*, std::any> {};
40
41 template <typename _nodeview_t, typename adjlist_t = py::set<Value_type<_nodeview_t>>,
42 typename adjlist_outer_dict_factory = py::dict<Value_type<_nodeview_t>, adjlist_t>>
43 class Graph {
44 public:
46 using Node = typename nodeview_t::value_type; // luk
47 // using dict = py::dict<const char*, std::any>;
48 // using graph_attr_dict_factory = dict;
49 // using edge_attr_dict_factory = dict;
50 // using node_attr_dict_factory = dict;
51 // using node_dict_factory = py::dict<Node, node_attr_dict_factory>;
52 // using adjlist_inner_dict_factory = py::dict<Node,
53 // edge_attr_dict_factory>;
55 using key_type = typename adjlist_t::key_type;
56 using value_type = typename adjlist_t::value_type;
57 using edge_t = std::pair<Node, Node>;
58 using node_t = Node;
59
60 size_t _num_of_edges = 0;
61
62 // std::vector<Node > _Nodes{}
64 // graph_attr_dict_factory graph{}; // dictionary for graph attributes
65 // node_dict_factory _node{}; // empty node attribute dict
67
68 // auto __getstate__() {
69 // attr = this->__dict__.copy();
70 // // remove lazy property attributes
71 // if ("nodes" : attr) {
72 // del attr["nodes"];
73 // }
74 // if ("edges" : attr) {
75 // del attr["edges"];
76 // }
77 // if ("degree" : attr) {
78 // del attr["degree"];
79 // }
80 // return attr;
81 // }
82
85 explicit Graph(const nodeview_t& Nodes)
86 : _node{Nodes},
87 _adj{} // py::dict???
88 {}
89
94 _adj(num_nodes) // std::vector
95 {}
96
97 // Graph(const Graph&) = delete; // don't copy
98 // Graph& operator=(const Graph&) = delete; // don't copy
99 // Graph(Graph&&) noexcept = default;
100
107 static auto end_points(edge_t& e) -> edge_t& { return e; }
108
115 static auto end_points(const edge_t& e) -> const edge_t& { return e; }
116
119 auto adj() const {
120 using T = std::remove_reference_t<decltype(this->_adj)>;
121 return AdjacencyView<const T&>(this->_adj);
122 }
123
126 auto adj() {
127 using T = std::remove_cv_t<decltype(this->_adj)>;
128 return AdjacencyView<T>(this->_adj);
129 }
130
133 auto _nodes_nbrs() const {
134 // @TODO support py:dict
135 return py::enumerate(this->_adj);
136 }
137
138 // auto null_vertex() const -> const Node&
139 // {
140 // return *(this->_node.end());
141 // }
142
143 // Node& null_vertex()
144 // {
145 // return *(this->_node.end());
146 // }
147
154 // auto get_name() {
155 // if (!this->graph.contains("name")) {
156 // return "";
157 // }
158 // return std::any_cast<const char*>(this->graph["name"]);
159 // }
160
161 // // @name.setter
162 // auto set_name(std::string_view s) { this->graph["name"] = std::any(s); }
163
166 auto begin() const { return std::begin(this->_node); }
167
170 auto end() const { return std::end(this->_node); }
171
175 auto contains(const Node& node) const -> bool { return this->_node.contains(node); }
176
180 auto operator[](const Node& node) const -> const auto& { return this->adj().at(node); }
181
185 auto at(const Node& node) const -> const auto& { return this->adj().at(node); }
186
190 auto operator[](const Node& node) -> auto& { return this->adj()[node]; }
191
194 auto nodes() {
195 using T = std::remove_reference_t<decltype(*this)>;
196 auto nodes = NodeView<T>(*this);
197 // Lazy View creation: overload the (class) property on the instance
198 // Then future gra.nodes use the existing View
199 // setattr doesn"t work because attribute already exists
200 // this->operator[]("nodes") = std::any(nodes);
201 return nodes;
202 }
203
206 auto number_of_nodes() const -> size_t { return this->_node.size(); }
207
210 auto order() const { return this->_node.size(); }
211
214 auto size() const -> size_t { return this->_node.size(); }
215
218 auto number_of_edges() const -> size_t { return this->_num_of_edges; }
219
224 std::vector<edge_t> result;
225 for (const auto& node : this->_node) {
226 for (const auto& nbr : this->_adj[node]) {
227 if (node < nbr) {
228 result.emplace_back(node, nbr);
229 }
230 }
231 }
232 return result;
233 }
234
238 auto has_node(const Node& node) const -> bool { return this->_node.contains(node); }
239
244 template <typename U = key_type> auto add_edge(const Node& node_u, const Node& node_v) ->
245 typename std::enable_if<std::is_same<U, value_type>::value>::type {
246 this->_adj[node_u].insert(node_v);
247 this->_adj[node_v].insert(node_u);
248 ++this->_num_of_edges;
249 }
250
255 template <typename U = key_type> auto add_edge(const Node& node_u, const Node& node_v) ->
256 typename std::enable_if<!std::is_same<U, value_type>::value>::type {
257 using T = typename adjlist_t::mapped_type;
258 auto data = this->_adj[node_u].get(node_v, T{});
259 this->_adj[node_u][node_v] = data;
260 this->_adj[node_v][node_u] = data;
261 ++this->_num_of_edges;
262 }
263
269 template <typename T> auto add_edge(const Node& node_u, const Node& node_v, const T& data) {
270 this->_adj[node_u][node_v] = data;
271 this->_adj[node_v][node_u] = data;
272 ++this->_num_of_edges;
273 }
274
278 template <typename C1> auto add_edges_from(const C1& edges) {
279 for (const auto& e : edges) {
280 this->add_edge(e.first, e.second);
281 }
282 }
283
289 template <typename C1, typename C2> auto add_edges_from(const C1& edges, const C2& data) {
290 auto it = data.begin();
291 for (const auto& e : edges) {
292 this->add_edge(e.first, e.second, *it);
293 ++it;
294 }
295 }
296
301 auto has_edge(const Node& node_u, const Node& node_v) const -> bool {
302 return this->_adj.at(node_u).contains(node_v);
303 }
304
308 auto degree(const Node& node) const { return this->_adj[node].size(); }
309
311 auto clear() {
312 this->_adj.clear();
313 // this->_node.clear();
314 // this->graph.clear();
315 }
316
322 template <typename F> auto for_each_edge(F&& func) const -> void {
323 for (const auto& node : this->_node) {
324 for (const auto& nbr : this->_adj[node]) {
325 if (node < nbr) {
326 std::forward<F>(func)(node, nbr);
327 }
328 }
329 }
330 }
331
334 auto is_multigraph() const { return false; }
335
338 auto is_directed() const { return false; }
339 };
340
344 std::vector<py::set<uint32_t>>>;
345
346 // template <typename nodeview_t,
347 // typename adjlist_t> Graph(int )
348 // -> Graph<decltype(py::range(1)), py::set<int>>;
349
350} // namespace xnetwork
Read-only map of maps of maps (view into a dict-of-dict-of-dict structure)
Definition coreviews.hpp:109
AdjacencyView(Atlas &d)
Construct an AdjacencyView from an Atlas container.
Definition coreviews.hpp:115
auto at(const T &key) const -> const auto &
Access element at specified key (const version)
Definition coreviews.hpp:79
auto begin() const
Get iterator to the beginning of the view.
Definition coreviews.hpp:55
auto size() const -> size_t
Get the number of elements in the view.
Definition coreviews.hpp:49
Undirected graph with arbitrary node types.
Definition graph.hpp:43
auto add_edge(const Node &node_u, const Node &node_v) -> typename std::enable_if<!std::is_same< U, value_type >::value >::type
Add an edge between two nodes (for complex key type, SFINAE)
Definition graph.hpp:255
auto size() const -> size_t
Get the number of nodes (same as number_of_nodes)
Definition graph.hpp:214
auto is_directed() const
Check if the graph is directed.
Definition graph.hpp:338
typename adjlist_t::value_type value_type
Definition graph.hpp:56
auto contains(const Node &node) const -> bool
Check if a node is in the graph.
Definition graph.hpp:175
static auto end_points(const edge_t &e) -> const edge_t &
For compatible with BGL adaptor.
Definition graph.hpp:115
auto operator[](const Node &node) const -> const auto &
Access adjacency dict of a node (const version)
Definition graph.hpp:180
auto edges() const -> std::vector< edge_t >
Return a vector of all edges as (u, v) pairs.
Definition graph.hpp:223
Graph(uint32_t num_nodes)
Construct a graph with a given number of integer nodes.
Definition graph.hpp:92
auto order() const
Get the number of nodes (same as number_of_nodes)
Definition graph.hpp:210
Graph(const nodeview_t &Nodes)
Construct a graph from a node container.
Definition graph.hpp:85
_nodeview_t nodeview_t
Definition graph.hpp:45
static auto end_points(edge_t &e) -> edge_t &
For compatible with BGL adaptor.
Definition graph.hpp:107
auto operator[](const Node &node) -> auto &
Access adjacency dict of a node (non-const version)
Definition graph.hpp:190
auto add_edge(const Node &node_u, const Node &node_v, const T &data)
Add an edge with attached data.
Definition graph.hpp:269
auto has_node(const Node &node) const -> bool
Check if the graph contains a node.
Definition graph.hpp:238
auto end() const
End iterator over nodes.
Definition graph.hpp:170
auto has_edge(const Node &node_u, const Node &node_v) const -> bool
Check if an edge exists between two nodes.
Definition graph.hpp:301
auto add_edges_from(const C1 &edges)
Add edges from a container of edge pairs.
Definition graph.hpp:278
size_t _num_of_edges
Number of edges in the graph (cached)
Definition graph.hpp:60
auto is_multigraph() const
Check if the graph is a multigraph.
Definition graph.hpp:334
auto nodes()
Get a NodeView of the graph.
Definition graph.hpp:194
auto at(const Node &node) const -> const auto &
Access adjacency dict of a node with bounds check (const version)
Definition graph.hpp:185
typename adjlist_t::key_type key_type
Definition graph.hpp:55
auto adj()
Get the adjacency mapping of the graph (non-const version)
Definition graph.hpp:126
nodeview_t _node
Container holding all nodes in the graph.
Definition graph.hpp:63
Node node_t
Definition graph.hpp:58
std::pair< Node, Node > edge_t
Definition graph.hpp:57
auto add_edge(const Node &node_u, const Node &node_v) -> typename std::enable_if< std::is_same< U, value_type >::value >::type
Add an edge between two nodes (for simple key type, SFINAE)
Definition graph.hpp:244
auto for_each_edge(F &&func) const -> void
Apply a callable to each edge without materializing a vector.
Definition graph.hpp:322
auto begin() const
Begin iterator over nodes.
Definition graph.hpp:166
typename nodeview_t::value_type Node
Definition graph.hpp:46
auto degree(const Node &node) const
Get the degree of a node.
Definition graph.hpp:308
auto clear()
Remove all nodes and edges from the graph.
Definition graph.hpp:311
auto _nodes_nbrs() const
Iterate over nodes and their neighbors.
Definition graph.hpp:133
auto number_of_nodes() const -> size_t
Get the number of nodes in the graph.
Definition graph.hpp:206
adjlist_outer_dict_factory _adj
Adjacency dictionary keyed by node.
Definition graph.hpp:66
auto add_edges_from(const C1 &edges, const C2 &data)
Add edges from a container with associated data.
Definition graph.hpp:289
auto adj() const
Get the adjacency mapping of the graph (const version)
Definition graph.hpp:119
auto number_of_edges() const -> size_t
Get the number of edges in the graph.
Definition graph.hpp:218
Read-only view classes for graph data structures.
typename T::value_type Value_type
Alias for the value_type of a container.
Definition graph.hpp:20
Definition hadlock.hpp:32
Definition digraphs.hpp:24
View classes for nodes, edges, and degrees in XNetwork graphs.