Skip to content
Snippets Groups Projects
Commit 02a19a58 authored by Jerome Hue's avatar Jerome Hue Committed by Grégoire Kubler
Browse files

feat : [Add] Heaviside Operator

parent d276d6dd
No related branches found
No related tags found
3 merge requests!279v0.4.0,!253v0.4.0,!215[Add] Heaviside Operator
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#include "aidge/operator/GenericOperator.hpp" #include "aidge/operator/GenericOperator.hpp"
#include "aidge/operator/GlobalAveragePooling.hpp" #include "aidge/operator/GlobalAveragePooling.hpp"
#include "aidge/operator/GridSample.hpp" #include "aidge/operator/GridSample.hpp"
#include "aidge/operator/Heaviside.hpp"
#include "aidge/operator/MatMul.hpp" #include "aidge/operator/MatMul.hpp"
#include "aidge/operator/MaxPooling.hpp" #include "aidge/operator/MaxPooling.hpp"
#include "aidge/operator/MetaOperator.hpp" #include "aidge/operator/MetaOperator.hpp"
......
/********************************************************************************
* 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_CORE_OPERATOR_HEAVISIDE_H_
#define AIDGE_CORE_OPERATOR_HEAVISIDE_H_
#include <memory>
#include <string>
#include <vector>
#include "aidge/backend/OperatorImpl.hpp"
#include "aidge/graph/Node.hpp"
#include "aidge/operator/Operator.hpp"
#include "aidge/operator/OperatorTensor.hpp"
#include "aidge/utils/Registrar.hpp"
#include "aidge/utils/StaticAttributes.hpp"
#include "aidge/utils/Types.h"
namespace Aidge {
enum class HeavisideAttr {
/**
* @brief The value used in the output tensor when the input is 0.
*/
Value
};
class Heaviside_Op
: public OperatorTensor,
public Registrable<
Heaviside_Op,
std::string,
std::function<std::shared_ptr<OperatorImpl>(const Heaviside_Op &)>> {
private:
using Attributes_ = StaticAttributes<HeavisideAttr, float>;
template <HeavisideAttr e>
using attr = typename Attributes_::template attr<e>;
const std::shared_ptr<Attributes_> mAttributes;
public:
static const std::string Type;
/*
* Compute the Heaviside step function for each element of the first input.
* Heaviside step function is defined as :
*
* \f[
* heaviside(input, values) = \begin{cases}
* 0 & \text{if input } < 0 \\
* values & \text{if input } = 0 \\
* 1 & \text{if input } > 0
* \end{cases}
* \f]
* */
Heaviside_Op(float value);
Heaviside_Op(const Heaviside_Op &op);
std::shared_ptr<Operator> clone() const override;
void setBackend(const std::string &name, DeviceIdx_t device = 0) override;
std::set<std::string> getAvailableBackends() const override;
static const std::vector<std::string> getInputsName() {
return {"data_input", "data_values"};
}
static const std::vector<std::string> getOutputsName() {
return {"output"};
}
inline std::shared_ptr<Attributes> attributes() const override {
return mAttributes;
}
inline float &value() const {
return mAttributes->template getAttr<HeavisideAttr::Value>();
}
};
/**
* @brief Create a Heaviside node.
*
* Initializes a Heaviside node that computes the Heaviside step function for each element
* of the input tensor, using the specified value for inputs equal to zero.
*
* @param value The value used in the output tensor when the input is 0.
* @param name Optional. The name of the node.
*
* @return A shared pointer to a Node representing the Heaviside operation.
*/
std::shared_ptr<Node> Heaviside(float value, const std::string &name = "");
} // namespace Aidge
namespace {
template <>
const char *const EnumStrings<Aidge::HeavisideAttr>::data[] = {"value"};
}
#endif /* AIDGE_CORE_OPERATOR_HEAVISIDE_H_ */
/********************************************************************************
* 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
*
********************************************************************************/
#include <pybind11/pybind11.h>
#include "aidge/operator/Heaviside.hpp"
#include "aidge/operator/OperatorTensor.hpp"
namespace py = pybind11;
namespace Aidge {
void init_Heaviside(py::module &m) {
py::class_<Heaviside_Op, std::shared_ptr<Heaviside_Op>, OperatorTensor>(
m,
"HeavisideOp",
py::multiple_inheritance(),
R"mydelimiter(
Initialize an Heaviside node. This node will compute a heaviside step function
on each element of the input tensor.
heaviside(input, values) = { 0 if input < 0
{ values if input == 0
{ 1 if input > 0
:param value : The value use for the output tensor when input is 0.
:type value : float
:param name : Name of the node.
)mydelimiter")
.def(py::init<float>(), py::arg("value"))
.def_static("get_inputs_name", &Heaviside_Op::getInputsName)
.def_static("get_outputs_name", &Heaviside_Op::getOutputsName)
.def_readonly_static("Type", &Heaviside_Op::Type);
declare_registrable<Heaviside_Op>(m, "HeavisideOp");
m.def("Heaviside", &Heaviside, py::arg("value"), py::arg("name") = "",
R"mydelimiter(
Initialize an Heaviside node. This node will compute a heaviside step function
on each element of the input tensor.
heaviside(input, values) = { 0 if input < 0
{ values if input == 0
{ 1 if input > 0
:param value : The value use for the output tensor when input is 0.
:type value : float
:param name : Name of the node.
)mydelimiter");
}
} // namespace Aidge
...@@ -48,6 +48,7 @@ void init_Gather(py::module&); ...@@ -48,6 +48,7 @@ void init_Gather(py::module&);
void init_GenericOperator(py::module&); void init_GenericOperator(py::module&);
void init_GlobalAveragePooling(py::module&); void init_GlobalAveragePooling(py::module&);
void init_GridSample(py::module&); void init_GridSample(py::module&);
void init_Heaviside(py::module&);
void init_Identity(py::module&); void init_Identity(py::module&);
void init_LeakyReLU(py::module&); void init_LeakyReLU(py::module&);
void init_MatMul(py::module&); void init_MatMul(py::module&);
...@@ -137,6 +138,7 @@ void init_Aidge(py::module& m) { ...@@ -137,6 +138,7 @@ void init_Aidge(py::module& m) {
init_GenericOperator(m); init_GenericOperator(m);
init_GlobalAveragePooling(m); init_GlobalAveragePooling(m);
init_GridSample(m); init_GridSample(m);
init_Heaviside(m);
init_Identity(m); init_Identity(m);
init_LeakyReLU(m); init_LeakyReLU(m);
init_MatMul(m); init_MatMul(m);
......
/********************************************************************************
* 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
*
********************************************************************************/
#include <cstddef> // std::size_t
#include <memory>
#include <stdexcept> // std::runtime_error
#include <string>
#include <vector>
#include "aidge/backend/OperatorImpl.hpp"
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/Heaviside.hpp"
#include "aidge/utils/ErrorHandling.hpp"
#include "aidge/utils/Types.h"
namespace Aidge {
// ----------------------------------------------------------- Heaviside_Op
// class
const std::string Heaviside_Op::Type = "Heaviside";
Heaviside_Op::Heaviside_Op(float value)
: OperatorTensor(Type, {InputCategory::Data}, 1),
mAttributes(
std::make_shared<Attributes_>(attr<HeavisideAttr::Value>(value))) {}
Heaviside_Op::Heaviside_Op(const Heaviside_Op &op)
: OperatorTensor(op), mAttributes(op.mAttributes) {
if (op.mImpl) {
SET_IMPL_MACRO(Heaviside_Op, *this, op.backend());
} else {
mImpl = nullptr;
}
}
std::shared_ptr<Aidge::Operator> Aidge::Heaviside_Op::clone() const {
return std::make_shared<Heaviside_Op>(*this);
}
void Heaviside_Op::setBackend(const std::string &name, DeviceIdx_t device) {
SET_IMPL_MACRO(Heaviside_Op, *this, name);
mOutputs[0]->setBackend(name, device);
}
std::set<std::string> Aidge::Heaviside_Op::getAvailableBackends() const {
return Registrar<Heaviside_Op>::getKeys();
}
// --------------------------------------------------------------- Free
// functions
NodePtr Heaviside(float value, const std::string &name) {
return std::make_shared<Node>(std::make_shared<Heaviside_Op>(value), name);
}
} // namespace Aidge
/********************************************************************************
* 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
*
********************************************************************************/
#include <catch2/catch_test_macros.hpp>
#include <catch2/generators/catch_generators_random.hpp>
#include <cstddef> // std::size_t
#include <memory>
#include <random> // std::mt19937, std::uniform_int_distribution
#include <vector>
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/Heaviside.hpp"
#include "aidge/operator/OperatorTensor.hpp"
namespace Aidge {
TEST_CASE("[core/operator] Heaviside_Op(forwardDims)",
"[Heaviside][forwardDims]") {
constexpr std::uint16_t NBTRIALS = 10;
// Create a random number generator
auto rd = Catch::Generators::Detail::getSeed;
std::mt19937 gen(rd());
std::uniform_int_distribution<std::size_t> dimsDist(1, 10);
std::uniform_int_distribution<std::size_t> nbDimsDist(1, 5);
// Create Heaviside Operator
std::shared_ptr<Node> myHeaviside = Heaviside(0.5);
auto op =
std::static_pointer_cast<OperatorTensor>(myHeaviside->getOperator());
// input_0
std::shared_ptr<Tensor> T0 = std::make_shared<Tensor>();
op->associateInput(0, T0);
SECTION("Scalar") {
// input 0
T0->resize({});
REQUIRE_NOTHROW(op->forwardDims());
REQUIRE((op->getOutput(0)->dims() == std::vector<std::size_t>()));
}
SECTION("+1-D Tensor") {
for (std::uint16_t trial = 0; trial < NBTRIALS; ++trial) {
const std::size_t nb_dims = nbDimsDist(gen);
std::vector<std::size_t> dims(nb_dims);
for (std::size_t i = 0; i < nb_dims; ++i) {
dims[i] = dimsDist(gen);
}
T0->resize(dims);
REQUIRE_NOTHROW(op->forwardDims());
REQUIRE((op->getOutput(0)->dims()) == dims);
}
}
}
} // namespace Aidge
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment