diff --git a/python_binding/operator/pybind_Expand.cpp b/python_binding/operator/pybind_Expand.cpp index ce8a32329ab51ea3086c689b0156b62244f752c2..c20e47e849bbfad7331b8f5f2de82bc32bda033e 100644 --- a/python_binding/operator/pybind_Expand.cpp +++ b/python_binding/operator/pybind_Expand.cpp @@ -50,11 +50,11 @@ void init_Expand(py::module &m) { declare_registrable<Expand_Op>(m, pyClassName); - m.def("expand", + m.def("Expand", &Expand, py::arg("name") = "", R"mydelimiter( - Initialize a node containing an expand operator. + Initialize a node containing an Expand operator. This operator will broadcast values given via input#0 to a shape given via input#1's values If one of the inputs has less dimensions than the other, dimension will be appended 1's to the left. diff --git a/python_binding/operator/pybind_Fold.cpp b/python_binding/operator/pybind_Fold.cpp new file mode 100644 index 0000000000000000000000000000000000000000..747abc1611a1a51d9b317de365b5036436b1494a --- /dev/null +++ b/python_binding/operator/pybind_Fold.cpp @@ -0,0 +1,107 @@ +#include <pybind11/pybind11.h> +#include <pybind11/stl.h> +#include <string> +#include <vector> +#include <array> + +#include "aidge/backend/OperatorImpl.hpp" +#include "aidge/data/Tensor.hpp" +#include "aidge/operator/Fold.hpp" +#include "aidge/operator/OperatorTensor.hpp" +#include "aidge/utils/Types.h" +#include "aidge/utils/Registrar.hpp" // declare_registrable + +namespace py = pybind11; +namespace Aidge { + +template <DimIdx_t DIM> +void declare_FoldOp(py::module &m) { + const std::string pyClassName("Fold" + std::to_string(DIM) + "DOp"); + py::class_<Fold_Op<DIM>, std::shared_ptr<Fold_Op<DIM>>, OperatorTensor>( + m, pyClassName.c_str(), + py::multiple_inheritance(), + R"mydelimiter( + Initialize a Fold operator. + + :param output_dims : The dimensions of output. + :type output_dims : List[int] + :param kernel_dims : The dimensions of the fold kernel (filter size). + :type kernel_dims : List[int] + :param stride_dims : The stride size for the fold. + :type stride_dims : List[int] + :param dilation_dims : The dilation size for the fold. + :type dilation_dims : List[int] + )mydelimiter") + .def(py::init([](const std::vector<DimSize_t>& output_dims, + const std::vector<DimSize_t>& kernel_dims, + const std::vector<DimSize_t> &stride_dims, + const std::vector<DimSize_t> &dilation_dims) { + AIDGE_ASSERT(output_dims.size() == DIM, "output_dims size [{}] does not match DIM [{}]", output_dims.size(), DIM); + AIDGE_ASSERT(kernel_dims.size() == DIM, "kernel_dims size [{}] does not match DIM [{}]", kernel_dims.size(), DIM); + AIDGE_ASSERT(stride_dims.size() == DIM, "stride_dims size [{}] does not match DIM [{}]", stride_dims.size(), DIM); + AIDGE_ASSERT(dilation_dims.size() == DIM, "dilation_dims size [{}] does not match DIM [{}]", dilation_dims.size(), DIM); + + return new Fold_Op<DIM>(to_array<DIM>(output_dims.begin()), to_array<DIM>(kernel_dims.begin()), to_array<DIM>(stride_dims.begin()), to_array<DIM>(dilation_dims.begin())); + }), py::arg("output_dims"), + py::arg("kernel_dims"), + py::arg("stride_dims") = std::vector<DimSize_t>(DIM,1), + py::arg("dilation_dims") = std::vector<DimSize_t>(DIM,1)) + .def_static("get_inputs_name", &Fold_Op<DIM>::getInputsName) + .def_static("get_outputs_name", &Fold_Op<DIM>::getOutputsName) + + .def_static("attributes_name", []() { + std::vector<std::string> result; + auto attributes = Fold_Op<DIM>::attributesName(); + for (size_t i = 0; i < size(EnumStrings<FoldAttr>::data); ++i) { + result.emplace_back(attributes[i]); + } + return result; + }) + .def_readonly_static("Type", &Fold_Op<DIM>::Type) + ; + + declare_registrable<Fold_Op<DIM>>(m, pyClassName); + + m.def(("Fold" + std::to_string(DIM) + "D").c_str(), [](const std::vector<DimSize_t>& output_dims, + const std::vector<DimSize_t>& kernel_dims, + const std::string& name, + const std::vector<DimSize_t> &stride_dims, + const std::vector<DimSize_t> &dilation_dims) { + AIDGE_ASSERT(output_dims.size() == DIM, "output_dims size [{}] does not match DIM [{}]", output_dims.size(), DIM); + AIDGE_ASSERT(kernel_dims.size() == DIM, "kernel_dims size [{}] does not match DIM [{}]", kernel_dims.size(), DIM); + AIDGE_ASSERT(stride_dims.size() == DIM, "stride_dims size [{}] does not match DIM [{}]", stride_dims.size(), DIM); + AIDGE_ASSERT(dilation_dims.size() == DIM, "dilation_dims size [{}] does not match DIM [{}]", dilation_dims.size(), DIM); + + return Fold<DIM>(to_array<DIM>(output_dims.begin()), to_array<DIM>(kernel_dims.begin()), name, to_array<DIM>(stride_dims.begin()), to_array<DIM>(dilation_dims.begin())); + }, + py::arg("output_dims"), + py::arg("kernel_dims"), + py::arg("name") = "", + py::arg("stride_dims") = std::vector<DimSize_t>(DIM,1), + py::arg("dilation_dims") = std::vector<DimSize_t>(DIM,1), + R"mydelimiter( + Initialize a node containing a Fold operator. + + :param output_dims : The dimensions of output. + :type output_dims : List[int] + :param kernel_dims : The dimensions of the fold kernel (filter size). + :type kernel_dims : List[int] + :param name : The name of the operator (optional). + :type name : str + :param stride_dims : The stride size for the fold (default is [1]). + :type stride_dims : List[int] + :param dilation_dims : The dilation size for the fold (default is [1]). + :type dilation_dims : List[int] + :return : A new Fold operator node. + :rtype : :py:class:`FoldOp` + )mydelimiter"); +} + + +void init_Fold(py::module &m) { +// declare_FoldOp<1>(m); + declare_FoldOp<2>(m); +// declare_FoldOp<3>(m); +} + +} // namespace Aidge diff --git a/python_binding/operator/pybind_Unfold.cpp b/python_binding/operator/pybind_Unfold.cpp new file mode 100644 index 0000000000000000000000000000000000000000..86f8f26d63ef1c59ad68842a6e7291fa4706e8e1 --- /dev/null +++ b/python_binding/operator/pybind_Unfold.cpp @@ -0,0 +1,97 @@ +#include <pybind11/pybind11.h> +#include <pybind11/stl.h> +#include <string> +#include <vector> +#include <array> + +#include "aidge/backend/OperatorImpl.hpp" +#include "aidge/data/Tensor.hpp" +#include "aidge/operator/Unfold.hpp" +#include "aidge/operator/OperatorTensor.hpp" +#include "aidge/utils/Types.h" +#include "aidge/utils/Registrar.hpp" // declare_registrable + +namespace py = pybind11; +namespace Aidge { + +template <DimIdx_t DIM> +void declare_UnfoldOp(py::module &m) { + const std::string pyClassName("Unfold" + std::to_string(DIM) + "DOp"); + py::class_<Unfold_Op<DIM>, std::shared_ptr<Unfold_Op<DIM>>, OperatorTensor>( + m, pyClassName.c_str(), + py::multiple_inheritance(), + R"mydelimiter( + Initialize a Unfold operator. + + :param kernel_dims : The dimensions of the unfold kernel (filter size). + :type kernel_dims : List[int] + :param stride_dims : The stride size for the unfold. + :type stride_dims : List[int] + :param dilation_dims : The dilation size for the unfold. + :type dilation_dims : List[int] + )mydelimiter") + .def(py::init([](const std::vector<DimSize_t>& kernel_dims, + const std::vector<DimSize_t> &stride_dims, + const std::vector<DimSize_t> &dilation_dims) { + AIDGE_ASSERT(kernel_dims.size() == DIM, "kernel_dims size [{}] does not match DIM [{}]", kernel_dims.size(), DIM); + AIDGE_ASSERT(stride_dims.size() == DIM, "stride_dims size [{}] does not match DIM [{}]", stride_dims.size(), DIM); + AIDGE_ASSERT(dilation_dims.size() == DIM, "dilation_dims size [{}] does not match DIM [{}]", dilation_dims.size(), DIM); + + return new Unfold_Op<DIM>(to_array<DIM>(kernel_dims.begin()), to_array<DIM>(stride_dims.begin()), to_array<DIM>(dilation_dims.begin())); + }), py::arg("kernel_dims"), + py::arg("stride_dims") = std::vector<DimSize_t>(DIM,1), + py::arg("dilation_dims") = std::vector<DimSize_t>(DIM,1)) + .def_static("get_inputs_name", &Unfold_Op<DIM>::getInputsName) + .def_static("get_outputs_name", &Unfold_Op<DIM>::getOutputsName) + + .def_static("attributes_name", []() { + std::vector<std::string> result; + auto attributes = Unfold_Op<DIM>::attributesName(); + for (size_t i = 0; i < size(EnumStrings<UnfoldAttr>::data); ++i) { + result.emplace_back(attributes[i]); + } + return result; + }) + .def_readonly_static("Type", &Unfold_Op<DIM>::Type) + ; + + declare_registrable<Unfold_Op<DIM>>(m, pyClassName); + + m.def(("Unfold" + std::to_string(DIM) + "D").c_str(), [](const std::vector<DimSize_t>& kernel_dims, + const std::string& name, + const std::vector<DimSize_t> &stride_dims, + const std::vector<DimSize_t> &dilation_dims) { + AIDGE_ASSERT(kernel_dims.size() == DIM, "kernel_dims size [{}] does not match DIM [{}]", kernel_dims.size(), DIM); + AIDGE_ASSERT(stride_dims.size() == DIM, "stride_dims size [{}] does not match DIM [{}]", stride_dims.size(), DIM); + AIDGE_ASSERT(dilation_dims.size() == DIM, "dilation_dims size [{}] does not match DIM [{}]", dilation_dims.size(), DIM); + + return Unfold<DIM>(to_array<DIM>(kernel_dims.begin()), name, to_array<DIM>(stride_dims.begin()), to_array<DIM>(dilation_dims.begin())); + }, + py::arg("kernel_dims"), + py::arg("name") = "", + py::arg("stride_dims") = std::vector<DimSize_t>(DIM,1), + py::arg("dilation_dims") = std::vector<DimSize_t>(DIM,1), + R"mydelimiter( + Initialize a node containing a Unfold operator. + + :param kernel_dims : The dimensions of the unfold kernel (filter size). + :type kernel_dims : List[int] + :param name : The name of the operator (optional). + :type name : str + :param stride_dims : The stride size for the unfold (default is [1]). + :type stride_dims : List[int] + :param dilation_dims : The dilation size for the unfold (default is [1]). + :type dilation_dims : List[int] + :return : A new Unfold operator node. + :rtype : :py:class:`UnfoldOp` + )mydelimiter"); +} + + +void init_Unfold(py::module &m) { +// declare_UnfoldOp<1>(m); + declare_UnfoldOp<2>(m); +// declare_UnfoldOp<3>(m); +} + +} // namespace Aidge diff --git a/python_binding/pybind_core.cpp b/python_binding/pybind_core.cpp index 7fef82847f3a9e5252e14c1aff584b21f182e36c..de045a4c928299200089adf060d0195ee7b59c60 100644 --- a/python_binding/pybind_core.cpp +++ b/python_binding/pybind_core.cpp @@ -61,6 +61,7 @@ void init_Erf(py::module&); void init_Expand(py::module&); void init_FC(py::module&); void init_Flatten(py::module&); +void init_Fold(py::module&); void init_Gather(py::module&); void init_GenericOperator(py::module&); void init_GlobalAveragePooling(py::module&); @@ -98,6 +99,7 @@ void init_Stack(py::module&); void init_Sub(py::module&); void init_Tanh(py::module&); void init_Transpose(py::module&); +void init_Unfold(py::module&); void init_Unsqueeze(py::module&); void init_WeightInterleaving(py::module&); @@ -169,6 +171,7 @@ void init_Aidge(py::module& m) { init_Expand(m); init_FC(m); init_Flatten(m); + init_Fold(m); init_Gather(m); init_GenericOperator(m); init_GlobalAveragePooling(m); @@ -205,6 +208,7 @@ void init_Aidge(py::module& m) { init_Sub(m); init_Tanh(m); init_Transpose(m); + init_Unfold(m); init_Unsqueeze(m); init_WeightInterleaving(m); diff --git a/src/graph/Node.cpp b/src/graph/Node.cpp index 33c336a843bcf168497cd86fea241d4ad2dec362..8a3975ece23e7951f51be455a13a0460813f1b73 100644 --- a/src/graph/Node.cpp +++ b/src/graph/Node.cpp @@ -349,11 +349,11 @@ void Aidge::Node::addChildOp(const std::shared_ptr<Node>& otherNode, const IOInd AIDGE_ASSERT(outId < nbOutputs(), "Output index (#{}) of the node {} (of type {}) is out of bound (it has {} outputs), when trying to add the child node {} (of type {})", outId, name(), type(), nbOutputs(), otherNode->name(), otherNode->type()); - if (otherNode.use_count() == 1) { - Log::debug("Node::addChild(): the node {} (of type {}) only holds a weak reference to the added child node {} (of type {})." - "If the child node goes out of scope, it will be destructed, leading to a dangling connection." - "To avoid this message, consider adding the child node to a GraphView first.", name(), type(), otherNode->name(), otherNode->type()); - } + // if (otherNode.use_count() == 1) { + // Log::debug("Node::addChild(): the node {} (of type {}) only holds a weak reference to the added child node {} (of type {})." + // "If the child node goes out of scope, it will be destructed, leading to a dangling connection." + // "To avoid this message, consider adding the child node to a GraphView first.", name(), type(), otherNode->name(), otherNode->type()); + // } if (otherNode->input(otherInId).second != gk_IODefaultIndex) { Log::notice("the {}-th Parent of the child node {} (of type {}) already existed", otherInId, otherNode->name(), otherNode->type()); }