From 621ad7ab14db5c107193705a7bf7d6417bd3b4f6 Mon Sep 17 00:00:00 2001 From: Charles Villard <charles.villard@cea.fr> Date: Thu, 17 Oct 2024 11:47:31 +0200 Subject: [PATCH 1/6] edit: Node: fix optional inputs in node treated as input graph --- include/aidge/graph/Node.hpp | 4 ++-- src/graph/Node.cpp | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/aidge/graph/Node.hpp b/include/aidge/graph/Node.hpp index 7319db245..d2357548e 100644 --- a/include/aidge/graph/Node.hpp +++ b/include/aidge/graph/Node.hpp @@ -286,10 +286,10 @@ public: if ((inputCategory(i) == InputCategory::Data || inputCategory(i) == InputCategory::OptionalData) && input(i).second == gk_IODefaultIndex) { - break; + return i; } } - return (i < nbInputs()) ? i : gk_IODefaultIndex; + return gk_IODefaultIndex; } /** diff --git a/src/graph/Node.cpp b/src/graph/Node.cpp index 74e0cab37..19eaa6d14 100644 --- a/src/graph/Node.cpp +++ b/src/graph/Node.cpp @@ -147,7 +147,9 @@ bool Aidge::Node::valid() const { Aidge::IOIndex_t Aidge::Node::getNbFreeDataInputs() const { IOIndex_t nbFreeDataIn = 0; for (IOIndex_t i = 0; i < nbInputs(); ++i) { - if (input(i).second == gk_IODefaultIndex) { + if ((inputCategory(i) == InputCategory::Data + || inputCategory(i) == InputCategory::OptionalData) + && input(i).second == gk_IODefaultIndex) { ++nbFreeDataIn; } } @@ -389,10 +391,17 @@ void Aidge::Node::addChild(const std::shared_ptr<Node>& otherNode, const IOIndex void Aidge::Node::addChild(std::shared_ptr<GraphView> otherView, const IOIndex_t outId, std::pair<std::shared_ptr<Node>, IOIndex_t> otherInId) { if (!otherInId.first) { - AIDGE_ASSERT(otherView->inputNodes().size() == 1U, + AIDGE_ASSERT(otherView->getNbFreeDataInputs() == 1U, "Input node of GraphView {} need to be specified, because it has more than one input ({} inputs), when trying to add it as a child of node {} (of type {})", otherView->name(), otherView->inputNodes().size(), name(), type()); - otherInId.first = *(otherView->inputNodes().begin()); + + otherInId.first = *(std::find_if( + otherView->inputNodes().begin(), + otherView->inputNodes().end(), + [](const auto &node) { + return node->getFirstFreeDataInput() != gk_IODefaultIndex; + } + )); } otherInId.second = (otherInId.second != gk_IODefaultIndex) ? otherInId.second -- GitLab From 990eed919a89a937557610b80cd5084231e16a50 Mon Sep 17 00:00:00 2001 From: Charles Villard <charles.villard@cea.fr> Date: Thu, 23 Jan 2025 16:24:39 +0100 Subject: [PATCH 2/6] WIP: filter input with bitwise category --- include/aidge/graph/GraphView.hpp | 2 +- include/aidge/operator/Operator.hpp | 17 ++++-- include/aidge/utils/BitwiseUtils.hpp | 87 ++++++++++++++++++++++++++++ src/graph/GraphView.cpp | 4 +- 4 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 include/aidge/utils/BitwiseUtils.hpp diff --git a/include/aidge/graph/GraphView.hpp b/include/aidge/graph/GraphView.hpp index 081c429e8..507d34f15 100644 --- a/include/aidge/graph/GraphView.hpp +++ b/include/aidge/graph/GraphView.hpp @@ -136,7 +136,7 @@ public: /////////////////////////////////////////////////////// public: /** @brief Get reference to the set of input Nodes. */ - std::set<NodePtr> inputNodes() const; + std::set<NodePtr> inputNodes(InputCategory filter = InputCategory::All) const; /** @brief Get reference to the set of output Nodes. */ std::set<NodePtr> outputNodes() const; diff --git a/include/aidge/operator/Operator.hpp b/include/aidge/operator/Operator.hpp index 0392dcfa2..35432faf2 100644 --- a/include/aidge/operator/Operator.hpp +++ b/include/aidge/operator/Operator.hpp @@ -17,6 +17,8 @@ #include <string> #include <vector> #include <utility> +#include <type_traits> +#include <cstddef> #ifdef PYBIND #include <pybind11/pybind11.h> @@ -27,6 +29,7 @@ #include "aidge/data/Data.hpp" #include "aidge/utils/Attributes.hpp" #include "aidge/utils/Types.h" +#include "aidge/utils/BitwiseUtils.hpp" #ifdef PYBIND namespace py = pybind11; @@ -56,12 +59,16 @@ enum class OperatorType { * @enum InputCategory * @brief Describes the category of an input for an operator. */ -enum class InputCategory { - Data, /**< Regular data input. */ - Param, /**< Parameter input. */ - OptionalData, /**< Optional data input. */ - OptionalParam /**< Optional parameter input. */ +enum class InputCategory : unsigned int { + Optional = 1 << 0, // First bit indicate if optional + Data = 1 << 1, /**< Regular data input. */ + OptionalData = (1 << 1) | Optional, /**< Optional data input. */ + Param = 1 << 2, /**< Parameter input. */ + OptionalParam = (1 << 2) | Optional, /**< Optional parameter input. */ + All = static_cast<unsigned int>(-1) }; +template <> +constexpr bool enable_bitmask_operators<InputCategory> = true; /** * @class Operator diff --git a/include/aidge/utils/BitwiseUtils.hpp b/include/aidge/utils/BitwiseUtils.hpp new file mode 100644 index 000000000..208115fa1 --- /dev/null +++ b/include/aidge/utils/BitwiseUtils.hpp @@ -0,0 +1,87 @@ +/******************************************************************************** + * Copyright (c) 2024 CEA-List + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ +#ifndef AIDGE_BITWISEUTILS_H_ +#define AIDGE_BITWISEUTILS_H_ + +#include <type_traits> + +namespace Aidge +{ + +// Define a trait to enable bitwise operators for an enum class +template <typename E> +constexpr bool enable_bitmask_operators = false; + +// Define bitwise OR +template <typename E> +constexpr typename std::enable_if_t<enable_bitmask_operators<E>, E> +operator|(E lhs, E rhs) { + using underlying = typename std::underlying_type_t<E>; + return static_cast<E>(static_cast<underlying>(lhs) | static_cast<underlying>(rhs)); +} + +// Define bitwise AND +template <typename E> +constexpr typename std::enable_if_t<enable_bitmask_operators<E>, E> +operator&(E lhs, E rhs) { + using underlying = typename std::underlying_type_t<E>; + return static_cast<E>(static_cast<underlying>(lhs) & static_cast<underlying>(rhs)); +} + +// Define bitwise XOR +template <typename E> +constexpr typename std::enable_if_t<enable_bitmask_operators<E>, E> +operator^(E lhs, E rhs) { + using underlying = typename std::underlying_type_t<E>; + return static_cast<E>(static_cast<underlying>(lhs) ^ static_cast<underlying>(rhs)); +} + +// Define bitwise NOT +template <typename E> +constexpr typename std::enable_if_t<enable_bitmask_operators<E>, E> +operator~(E value) { + using underlying = typename std::underlying_type_t<E>; + return static_cast<E>(~static_cast<underlying>(value)); +} + +// Define compound OR assignment +template <typename E> +constexpr typename std::enable_if_t<enable_bitmask_operators<E>, E&> +operator|=(E& lhs, E rhs) { + lhs = lhs | rhs; + return lhs; +} + +// Define compound AND assignment +template <typename E> +constexpr typename std::enable_if_t<enable_bitmask_operators<E>, E&> +operator&=(E& lhs, E rhs) { + lhs = lhs & rhs; + return lhs; +} + +// Define compound XOR assignment +template <typename E> +constexpr typename std::enable_if_t<enable_bitmask_operators<E>, E&> +operator^=(E& lhs, E rhs) { + lhs = lhs ^ rhs; + return lhs; +} + +template <typename E> +constexpr auto to_underlying(E e) noexcept +{ + return static_cast<std::underlying_type_t<E>>(e); +} + +} // namespace Aidge + +#endif // diff --git a/src/graph/GraphView.cpp b/src/graph/GraphView.cpp index c45bacf46..9d6557054 100644 --- a/src/graph/GraphView.cpp +++ b/src/graph/GraphView.cpp @@ -299,11 +299,11 @@ void Aidge::GraphView::setRootNode(NodePtr node) { // TENSOR MANAGEMENT /////////////////////////////////////////////////////// -std::set<std::shared_ptr<Aidge::Node>> Aidge::GraphView::inputNodes() const { +std::set<std::shared_ptr<Aidge::Node>> Aidge::GraphView::inputNodes(InputCategory filter) const { std::set<std::shared_ptr<Aidge::Node>> nodes; for (const auto& node : mInputNodes) { // Do not include dummy inputs - if (node.first) { + if (node.first && to_underlying(node.first->inputCategory(node.second) & filter)) { nodes.insert(node.first); } } -- GitLab From 12f38762985153309c772cb3b076adf6844babb6 Mon Sep 17 00:00:00 2001 From: Charles Villard <charles.villard@cea.fr> Date: Thu, 30 Jan 2025 17:24:39 +0100 Subject: [PATCH 3/6] add: pybind: add filter using bitwise enum --- python_binding/graph/pybind_GraphView.cpp | 1 + python_binding/operator/pybind_Operator.cpp | 12 +++++++----- python_binding/pybind_core.cpp | 12 ++++++------ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/python_binding/graph/pybind_GraphView.cpp b/python_binding/graph/pybind_GraphView.cpp index d1b99c305..4abb07fac 100644 --- a/python_binding/graph/pybind_GraphView.cpp +++ b/python_binding/graph/pybind_GraphView.cpp @@ -50,6 +50,7 @@ void init_GraphView(py::module& m) { )mydelimiter") .def("get_input_nodes", &GraphView::inputNodes, + py::arg("filter") = Aidge::InputCategory::All, R"mydelimiter( Get set of input Nodes. diff --git a/python_binding/operator/pybind_Operator.cpp b/python_binding/operator/pybind_Operator.cpp index 18708adee..94b41f691 100644 --- a/python_binding/operator/pybind_Operator.cpp +++ b/python_binding/operator/pybind_Operator.cpp @@ -28,11 +28,13 @@ void init_Operator(py::module& m){ .value("Data", OperatorType::Data) .value("Tensor", OperatorType::Tensor); - py::enum_<InputCategory>(m, "InputCategory") - .value("Data", InputCategory::Data) - .value("Param", InputCategory::Param) - .value("OptionalData", InputCategory::OptionalData) - .value("OptionalParam", InputCategory::OptionalParam); + py::enum_<Aidge::InputCategory>(m, "InputCategory", py::arithmetic()) + .value("Optional", Aidge::InputCategory::Optional) + .value("Data", Aidge::InputCategory::Data) + .value("OptionalData", Aidge::InputCategory::OptionalData) + .value("Param", Aidge::InputCategory::Param) + .value("OptionalParam", Aidge::InputCategory::OptionalParam) + .value("All", Aidge::InputCategory::All); py::class_<Operator, std::shared_ptr<Operator>>(m, "Operator") .def("__repr__", &Operator::repr) diff --git a/python_binding/pybind_core.cpp b/python_binding/pybind_core.cpp index 61a0a271c..ea738ccea 100644 --- a/python_binding/pybind_core.cpp +++ b/python_binding/pybind_core.cpp @@ -135,12 +135,6 @@ void init_Aidge(py::module& m) { init_Attributes(m); init_Spikegen(m); - init_Node(m); - init_GraphView(m); - init_OpArgs(m); - init_Connector(m); - init_SinglePassGraphMatching(m); - init_OperatorImpl(m); init_Log(m); init_Operator(m); @@ -149,6 +143,12 @@ void init_Aidge(py::module& m) { init_StaticAnalysis(m); init_DynamicAnalysis(m); + init_Node(m); + init_GraphView(m); + init_OpArgs(m); + init_Connector(m); + init_SinglePassGraphMatching(m); + init_Abs(m); init_Add(m); init_And(m); -- GitLab From d564899aebb7bfaa021aaa635c4f5e3153c8f37d Mon Sep 17 00:00:00 2001 From: Charles Villard <charles.villard@cea.fr> Date: Fri, 14 Feb 2025 07:32:06 +0100 Subject: [PATCH 4/6] edit: Operator: inline bitwise operation --- include/aidge/operator/Operator.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/aidge/operator/Operator.hpp b/include/aidge/operator/Operator.hpp index 35432faf2..61b1407aa 100644 --- a/include/aidge/operator/Operator.hpp +++ b/include/aidge/operator/Operator.hpp @@ -68,7 +68,7 @@ enum class InputCategory : unsigned int { All = static_cast<unsigned int>(-1) }; template <> -constexpr bool enable_bitmask_operators<InputCategory> = true; +inline constexpr bool enable_bitmask_operators<InputCategory> = true; /** * @class Operator -- GitLab From da1f66657b246710443176e1678090dd82a27f18 Mon Sep 17 00:00:00 2001 From: Charles Villard <charles.villard@cea.fr> Date: Thu, 20 Mar 2025 15:20:28 +0100 Subject: [PATCH 5/6] edit: Operator.hpp: preprocessor check compiler for compatibility --- include/aidge/operator/Operator.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/aidge/operator/Operator.hpp b/include/aidge/operator/Operator.hpp index 61b1407aa..b53c47c18 100644 --- a/include/aidge/operator/Operator.hpp +++ b/include/aidge/operator/Operator.hpp @@ -67,8 +67,16 @@ enum class InputCategory : unsigned int { OptionalParam = (1 << 2) | Optional, /**< Optional parameter input. */ All = static_cast<unsigned int>(-1) }; + + +#ifdef _MSC_VER +template <> +constexpr bool enable_bitmask_operators<InputCategory> = true; +#else template <> inline constexpr bool enable_bitmask_operators<InputCategory> = true; +#endif + /** * @class Operator -- GitLab From f8378f9526df995edd7d4e25e6812b9823e757b4 Mon Sep 17 00:00:00 2001 From: Charles Villard <charles.villard@cea.fr> Date: Wed, 26 Mar 2025 14:15:28 +0000 Subject: [PATCH 6/6] Change old data check to new bitwise filter --- include/aidge/graph/Node.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/aidge/graph/Node.hpp b/include/aidge/graph/Node.hpp index d2357548e..c06cf0c8b 100644 --- a/include/aidge/graph/Node.hpp +++ b/include/aidge/graph/Node.hpp @@ -283,7 +283,7 @@ public: inline IOIndex_t getFirstFreeDataInput() const { IOIndex_t i = 0; for (; i < nbInputs(); ++i) { - if ((inputCategory(i) == InputCategory::Data || inputCategory(i) == InputCategory::OptionalData) + if (to_underlying(inputCategory(i) & InputCategory::Data) && input(i).second == gk_IODefaultIndex) { return i; -- GitLab