Skip to main content

Graph Class

Directed acyclic graph of hybrid nodes with named ports. More...

Declaration

class simaai::neat::graph::Graph { ... }

Included Headers

#include <Graph.h>

Public Member Typedefs Index

usingNodePtr = std::shared_ptr< Node >

Shared-pointer type used to hold a runtime Node. More...

Public Constructors Index

Graph ()=default

Construct an empty graph. More...

Public Member Functions Index

NodeIdadd (NodePtr node)

Add a node to the graph. More...

const NodePtr &node (NodeId id) const

Look up a node by id. Throws std::out_of_range for an invalid id. More...

std::size_tnode_count () const noexcept

Number of nodes in the graph. More...

boolempty () const noexcept

True iff the graph holds no nodes. More...

PortIdintern_port (std::string_view name)

Intern a port name and return its compact PortId. More...

const std::string &port_name (PortId id) const

Return the human-readable port name for a PortId. Throws on invalid id. More...

std::size_tport_count () const noexcept

Number of unique port names interned in this graph. More...

const std::vector< std::string > &port_names () const noexcept

All interned port names, indexable by PortId. More...

voidconnect (NodeId from, NodeId to, const std::string &from_port="out", const std::string &to_port="in")

Connect from's named output port to to's named input port. More...

const std::vector< Edge > &edges () const noexcept

All edges in insertion order. More...

const Edge &edge (std::size_t idx) const

Look up an edge by index. Throws on invalid index. More...

const std::vector< std::size_t > &out_edges (NodeId id) const

Indices into edges() for outgoing edges of id. More...

const std::vector< std::size_t > &in_edges (NodeId id) const

Indices into edges() for incoming edges of id. More...

std::size_tout_degree (NodeId id) const

Number of outgoing edges from id. More...

std::size_tin_degree (NodeId id) const

Number of incoming edges to id. More...

std::vector< NodeId >topo_order () const

Topologically sort the graph. More...

boolis_dag () const

True iff the graph has no cycles. More...

Private Member Functions Index

voidvalidate_id_ (NodeId id, const char *where) const
boolhas_edge_ (NodeId from, NodeId to, PortId from_port, PortId to_port) const

Private Member Attributes Index

std::vector< NodePtr >nodes_
std::vector< Edge >edges_
std::vector< std::vector< std::size_t > >out_edges_
std::vector< std::vector< std::size_t > >in_edges_
std::vector< std::string >port_names_
std::unordered_map< std::string, PortId >port_ids_

Description

Directed acyclic graph of hybrid nodes with named ports.

Edges carry interned port identifiers at both endpoints (from_port and to_port), letting a node distinguish multiple inputs (e.g., "left" and "right") and multiple outputs (e.g., "main" and "telemetry") without inventing new types. Port names are interned to compact PortIds so the executor doesn't pay string-compare costs at dispatch time.

Construct one of these via GraphSession; consume via GraphRun / StageExecutor.

See Also

GraphSession, GraphRun, StageExecutor

Definition at line 50 of file Graph.h.

Public Member Typedefs

NodePtr

using simaai::neat::graph::Graph::NodePtr = std::shared_ptr<Node>

Shared-pointer type used to hold a runtime Node.

Definition at line 53 of file Graph.h.

53 using NodePtr = std::shared_ptr<Node>;

Public Constructors

Graph()

simaai::neat::graph::Graph::Graph ()
default

Construct an empty graph.

Definition at line 56 of file Graph.h.

Public Member Functions

add()

NodeId simaai::neat::graph::Graph::add (NodePtr node)
inline

Add a node to the graph.

Returns

Stable NodeId for the inserted node.

Exceptions
std::invalid_argument

if node is null.

Definition at line 67 of file Graph.h.

68 if (!node) {
69 throw std::invalid_argument("graph::Graph::add: node is null");
70 }
71 const NodeId id = nodes_.size();
72 nodes_.push_back(std::move(node));
73 out_edges_.emplace_back();
74 in_edges_.emplace_back();
75 return id;
76 }

connect()

void simaai::neat::graph::Graph::connect (NodeId from, NodeId to, const std::string & from_port="out", const std::string & to_port="in")
inline

Connect from's named output port to to's named input port.

Defaults connect from:"out"to:"in". Self-loops are rejected; duplicate edges (same endpoints + same port pair) are silently ignored.

Parameters
from

Source node id.

to

Destination node id.

from_port

Output port name on from (default "out").

to_port

Input port name on to (default "in").

Exceptions
std::invalid_argument

on self-loop or invalid id.

Definition at line 153 of file Graph.h.

153 void connect(NodeId from, NodeId to, const std::string& from_port = "out",
154 const std::string& to_port = "in") {
155 validate_id_(from, "graph::Graph::connect(from)");
156 validate_id_(to, "graph::Graph::connect(to)");
157 if (from == to) {
158 throw std::invalid_argument("graph::Graph::connect: self-loop is not allowed");
159 }
160 const PortId f = intern_port(from_port);
161 const PortId t = intern_port(to_port);
162
163 if (has_edge_(from, to, f, t))
164 return;
165
166 edges_.push_back({from, f, to, t});
167 const std::size_t idx = edges_.size() - 1;
168 out_edges_[from].push_back(idx);
169 in_edges_[to].push_back(idx);
170 }

edge()

const Edge & simaai::neat::graph::Graph::edge (std::size_t idx)
inline

Look up an edge by index. Throws on invalid index.

Definition at line 178 of file Graph.h.

178 const Edge& edge(std::size_t idx) const {
179 if (idx >= edges_.size()) {
180 throw std::out_of_range("graph::Graph::edge: invalid index");
181 }
182 return edges_[idx];
183 }

edges()

const std::vector< Edge > & simaai::neat::graph::Graph::edges ()
inline noexcept

All edges in insertion order.

Definition at line 173 of file Graph.h.

173 const std::vector<Edge>& edges() const noexcept {
174 return edges_;
175 }

empty()

bool simaai::neat::graph::Graph::empty ()
inline noexcept

True iff the graph holds no nodes.

Definition at line 89 of file Graph.h.

89 bool empty() const noexcept {
90 return nodes_.empty();
91 }

in_degree()

std::size_t simaai::neat::graph::Graph::in_degree (NodeId id)
inline

Number of incoming edges to id.

Definition at line 204 of file Graph.h.

204 std::size_t in_degree(NodeId id) const {
205 validate_id_(id, "graph::Graph::in_degree");
206 return in_edges_[id].size();
207 }

in_edges()

const std::vector< std::size_t > & simaai::neat::graph::Graph::in_edges (NodeId id)
inline

Indices into edges() for incoming edges of id.

Definition at line 192 of file Graph.h.

192 const std::vector<std::size_t>& in_edges(NodeId id) const {
193 validate_id_(id, "graph::Graph::in_edges");
194 return in_edges_[id];
195 }

intern_port()

PortId simaai::neat::graph::Graph::intern_port (std::string_view name)
inline

Intern a port name and return its compact PortId.

Repeated calls with the same name return the same id. Ids are dense and stable for the lifetime of the graph.

Exceptions
std::invalid_argument

if name is empty.

Definition at line 105 of file Graph.h.

105 PortId intern_port(std::string_view name) {
106 const std::string key(name);
107 if (key.empty()) {
108 throw std::invalid_argument("graph::Graph::intern_port: empty port name");
109 }
110 auto it = port_ids_.find(key);
111 if (it != port_ids_.end())
112 return it->second;
113 const PortId id = static_cast<PortId>(port_names_.size());
114 port_names_.push_back(key);
115 port_ids_.emplace(port_names_.back(), id);
116 return id;
117 }

is_dag()

bool simaai::neat::graph::Graph::is_dag ()
inline

True iff the graph has no cycles.

Definition at line 255 of file Graph.h.

255 bool is_dag() const {
256 try {
257 (void)topo_order();
258 return true;
259 } catch (...) {
260 return false;
261 }
262 }

node()

const NodePtr & simaai::neat::graph::Graph::node (NodeId id)
inline

Look up a node by id. Throws std::out_of_range for an invalid id.

Definition at line 79 of file Graph.h.

79 const NodePtr& node(NodeId id) const {
80 validate_id_(id, "graph::Graph::node");
81 return nodes_[id];
82 }

node_count()

std::size_t simaai::neat::graph::Graph::node_count ()
inline noexcept

Number of nodes in the graph.

Definition at line 85 of file Graph.h.

85 std::size_t node_count() const noexcept {
86 return nodes_.size();
87 }

out_degree()

std::size_t simaai::neat::graph::Graph::out_degree (NodeId id)
inline

Number of outgoing edges from id.

Definition at line 198 of file Graph.h.

198 std::size_t out_degree(NodeId id) const {
199 validate_id_(id, "graph::Graph::out_degree");
200 return out_edges_[id].size();
201 }

out_edges()

const std::vector< std::size_t > & simaai::neat::graph::Graph::out_edges (NodeId id)
inline

Indices into edges() for outgoing edges of id.

Definition at line 186 of file Graph.h.

186 const std::vector<std::size_t>& out_edges(NodeId id) const {
187 validate_id_(id, "graph::Graph::out_edges");
188 return out_edges_[id];
189 }

port_count()

std::size_t simaai::neat::graph::Graph::port_count ()
inline noexcept

Number of unique port names interned in this graph.

Definition at line 128 of file Graph.h.

128 std::size_t port_count() const noexcept {
129 return port_names_.size();
130 }

port_name()

const std::string & simaai::neat::graph::Graph::port_name (PortId id)
inline

Return the human-readable port name for a PortId. Throws on invalid id.

Definition at line 120 of file Graph.h.

120 const std::string& port_name(PortId id) const {
121 if (id >= port_names_.size()) {
122 throw std::out_of_range("graph::Graph::port_name: invalid port id");
123 }
124 return port_names_[id];
125 }

port_names()

const std::vector< std::string > & simaai::neat::graph::Graph::port_names ()
inline noexcept

All interned port names, indexable by PortId.

Definition at line 133 of file Graph.h.

133 const std::vector<std::string>& port_names() const noexcept {
134 return port_names_;
135 }

topo_order()

std::vector< NodeId > simaai::neat::graph::Graph::topo_order ()
inline

Topologically sort the graph.

Exceptions
std::runtime_error

if the graph has a cycle.

Definition at line 217 of file Graph.h.

217 std::vector<NodeId> topo_order() const {
218 const std::size_t n = nodes_.size();
219 std::vector<std::size_t> indeg(n, 0);
220 for (NodeId i = 0; i < n; ++i)
221 indeg[i] = in_edges_[i].size();
222
223 std::queue<NodeId> q;
224 for (NodeId i = 0; i < n; ++i) {
225 if (indeg[i] == 0)
226 q.push(i);
227 }
228
229 std::vector<NodeId> order;
230 order.reserve(n);
231
232 while (!q.empty()) {
233 NodeId u = q.front();
234 q.pop();
235 order.push_back(u);
236
237 for (const std::size_t eidx : out_edges_[u]) {
238 const Edge& e = edges_[eidx];
239 if (indeg[e.to] == 0) {
240 continue;
241 }
242 indeg[e.to]--;
243 if (indeg[e.to] == 0)
244 q.push(e.to);
245 }
246 }
247
248 if (order.size() != n) {
249 throw std::runtime_error("graph::Graph::topo_order: cycle detected (graph is not a DAG)");
250 }
251 return order;
252 }

Private Member Functions

has_edge_()

bool simaai::neat::graph::Graph::has_edge_ (NodeId from, NodeId to, PortId from_port, PortId to_port)
inline

Definition at line 271 of file Graph.h.

271 bool has_edge_(NodeId from, NodeId to, PortId from_port, PortId to_port) const {
272 for (const std::size_t eidx : out_edges_[from]) {
273 const Edge& e = edges_[eidx];
274 if (e.from == from && e.to == to && e.from_port == from_port && e.to_port == to_port) {
275 return true;
276 }
277 }
278 return false;
279 }

validate_id_()

void simaai::neat::graph::Graph::validate_id_ (NodeId id, const char * where)
inline

Definition at line 265 of file Graph.h.

265 void validate_id_(NodeId id, const char* where) const {
266 if (id >= nodes_.size()) {
267 throw std::out_of_range(std::string(where) + ": invalid NodeId");
268 }
269 }

Private Member Attributes

edges_

std::vector<Edge> simaai::neat::graph::Graph::edges_

Definition at line 282 of file Graph.h.

282 std::vector<Edge> edges_;

in_edges_

std::vector<std::vector<std::size_t> > simaai::neat::graph::Graph::in_edges_

Definition at line 284 of file Graph.h.

284 std::vector<std::vector<std::size_t>> in_edges_;

nodes_

std::vector<NodePtr> simaai::neat::graph::Graph::nodes_

Definition at line 281 of file Graph.h.

281 std::vector<NodePtr> nodes_;

out_edges_

std::vector<std::vector<std::size_t> > simaai::neat::graph::Graph::out_edges_

Definition at line 283 of file Graph.h.

283 std::vector<std::vector<std::size_t>> out_edges_;

port_ids_

std::unordered_map<std::string, PortId> simaai::neat::graph::Graph::port_ids_

Definition at line 287 of file Graph.h.

287 std::unordered_map<std::string, PortId> port_ids_;

port_names_

std::vector<std::string> simaai::neat::graph::Graph::port_names_

Definition at line 286 of file Graph.h.

286 std::vector<std::string> port_names_;

The documentation for this class was generated from the following file:


Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.9.8.