23#include <unordered_map>
33namespace shamrock::solvergraph {
35 using SolverGraphNodeCheck = std::function<bool(
const std::shared_ptr<INode> &node)>;
36 using SolverGraphEdgeCheck = std::function<bool(
const std::shared_ptr<IEdge> &edge)>;
40 SolverGraphNodeCheck node_check;
41 SolverGraphEdgeCheck edge_check;
44 return {.name = {}, .node_check =
nullptr, .edge_check =
nullptr};
47 inline bool check_node(
const std::shared_ptr<INode> &node)
const {
50 "node == nullptr is not allowed, please pass a shared pointer with a valid "
56 return (node_check) (node);
59 inline bool check_edge(
const std::shared_ptr<IEdge> &edge)
const {
62 "edge == nullptr is not allowed, please pass a shared pointer with a valid "
68 return (edge_check) (edge);
71 inline bool is_active()
const {
return bool(node_check) || bool(edge_check); }
112 std::unordered_map<std::string, std::shared_ptr<INode>> nodes = {};
115 std::unordered_map<std::string, std::shared_ptr<IEdge>> edges = {};
121 : constraint(std::move(graph_constraint)) {}
128 SolverGraph() =
default;
136 return SolverGraph{std::move(graph_constraint)};
148 const std::string &name, std::shared_ptr<INode> node) {
150 if (!constraint.check_node(node)) {
152 "Solvergraph constraint '{}' rejected node '{}' (label='{}', uuid={})",
159 const auto [it, inserted] = nodes.try_emplace(name, std::move(node));
162 shambase::format(
"Node already exists: {}", name));
176 const std::string &name, std::shared_ptr<IEdge> edge) {
178 if (!constraint.check_edge(edge)) {
180 "Solvergraph constraint '{}' rejected edge '{}' (label='{}', uuid={})",
187 const auto [it, inserted] = edges.try_emplace(name, std::move(edge));
190 shambase::format(
"Edge already exists: {}", name));
203 auto it = nodes.find(name);
204 if (it == nodes.end()) {
206 shambase::format(
"Node does not exist: {}", name));
213 auto it = nodes.find(name);
214 if (it == nodes.end()) {
216 shambase::format(
"Node does not exist: {}", name));
229 auto it = edges.find(name);
230 if (it == edges.end()) {
232 shambase::format(
"Edge does not exist: {}", name));
239 auto it = edges.find(name);
240 if (it == edges.end()) {
242 shambase::format(
"Edge does not exist: {}", name));
253 inline bool has_node(
const std::string &name)
const {
254 return nodes.find(name) != nodes.end();
263 inline bool has_edge(
const std::string &name)
const {
264 return edges.find(name) != edges.end();
321 inline std::shared_ptr<T>
register_node(
const std::string &name, T &&node) {
322 static_assert(std::is_base_of<INode, T>::value,
"T must derive from INode");
341 inline std::shared_ptr<T>
register_edge(
const std::string &name, T &&edge) {
342 static_assert(std::is_base_of<IEdge, T>::value,
"T must derive from IEdge");
363 shambase::format(
"Node exists but is not from the requested type: {}", name));
370 inline std::shared_ptr<T>
get_node_ptr(
const std::string &name)
const {
374 shambase::format(
"Node exists but is not from the requested type: {}", name));
395 shambase::format(
"Edge exists but is not from the requested type: {}", name));
402 inline std::shared_ptr<T>
get_edge_ptr(
const std::string &name)
const {
406 shambase::format(
"Edge exists but is not from the requested type: {}", name));
457 std::vector<std::string> ret{};
458 ret.reserve(edges.size());
460 for (
const auto &entry : edges) {
461 ret.push_back(entry.first);
463 std::sort(ret.begin(), ret.end());
469 std::vector<std::string> ret{};
470 ret.reserve(nodes.size());
472 for (
const auto &entry : nodes) {
473 ret.push_back(entry.first);
475 std::sort(ret.begin(), ret.end());
Inode is node between data edges, takes multiple inputs, multiple outputs.
std::shared_ptr< INode > & get_node_ptr_base(const std::string &name)
Retrieve a node by name as a shared pointer to the base interface.
std::vector< std::string > get_edge_names() const
Returns edge registration keys in lexicographic order (deterministic).
T & get_edge_ref(const std::string &name)
Get a typed reference to an edge by name.
const std::shared_ptr< INode > & get_node_ptr_base(const std::string &name) const
const variant
std::shared_ptr< T > get_edge_ptr(const std::string &name)
Get a typed shared pointer to an edge by name.
IEdge & get_edge_ref_base(const std::string &name)
Get a reference to an edge by name through the base interface.
bool has_edge(const std::string &name) const
Check whether an edge with the given name exists.
std::shared_ptr< T > get_edge_ptr(const std::string &name) const
const variant
std::shared_ptr< T > register_edge(const std::string &name, T &&edge)
Register an edge with automatic type deduction and shared pointer creation.
const std::shared_ptr< IEdge > & get_edge_ptr_base(const std::string &name) const
const variant
bool has_node(const std::string &name) const
Check whether a node with the given name exists.
std::shared_ptr< T > get_node_ptr(const std::string &name)
Get a typed shared pointer to a node by name.
std::shared_ptr< INode > register_node_ptr_base(const std::string &name, std::shared_ptr< INode > node)
Register a node with the graph using a shared pointer.
const T & get_edge_ref(const std::string &name) const
const variant
std::shared_ptr< T > get_node_ptr(const std::string &name) const
const variant
const INode & get_node_ref_base(const std::string &name) const
const variant
std::shared_ptr< IEdge > & get_edge_ptr_base(const std::string &name)
Retrieve an edge by name as a shared pointer to the base interface.
std::shared_ptr< T > register_node(const std::string &name, T &&node)
Register a node with automatic type deduction and shared pointer creation.
const IEdge & get_edge_ref_base(const std::string &name) const
const variant
std::vector< std::string > get_node_names() const
Returns node registration keys in lexicographic order (deterministic).
INode & get_node_ref_base(const std::string &name)
Get a reference to a node by name through the base interface.
const T & get_node_ref(const std::string &name) const
const variant
T & get_node_ref(const std::string &name)
Get a typed reference to a node by name.
std::shared_ptr< IEdge > register_edge_ptr_base(const std::string &name, std::shared_ptr< IEdge > edge)
Register an edge with the graph using a shared pointer.
static SolverGraph with_constraint(SolverGraphConstraint graph_constraint)
Create a solver graph with registration constraints.
This header file contains utility functions related to exception handling in the code.
void throw_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Throw an exception and append the source location to it.
T & get_check_ref(const std::unique_ptr< T > &ptr, SourceLocation loc=SourceLocation())
Takes a std::unique_ptr and returns a reference to the object it holds. It throws a std::runtime_erro...
ExcptTypes make_except_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Create an exception with a message and a location.