Crocoddyl
Loading...
Searching...
No Matches
weighted-smooth-1norm.hpp
1
2// BSD 3-Clause License
3//
4// Copyright (C) 2026, Heriot-Watt University
5// Copyright note valid unless otherwise stated in individual files.
6// All rights reserved.
8
9#ifndef CROCODDYL_CORE_ACTIVATIONS_WEIGHTED_SMOOTH_1NORM_HPP_
10#define CROCODDYL_CORE_ACTIVATIONS_WEIGHTED_SMOOTH_1NORM_HPP_
11
12#include "crocoddyl/core/activation-base.hpp"
13#include "crocoddyl/core/fwd.hpp"
14
15namespace crocoddyl {
16
39template <typename _Scalar>
41 : public ActivationModelAbstractTpl<_Scalar> {
42 public:
43 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
44 CROCODDYL_DERIVED_CAST(ActivationModelBase,
46
47 typedef _Scalar Scalar;
48 typedef MathBaseTpl<Scalar> MathBase;
49 typedef ActivationModelAbstractTpl<Scalar> Base;
50 typedef ActivationDataAbstractTpl<Scalar> ActivationDataAbstract;
52 typedef typename MathBase::VectorXs VectorXs;
53
61 const VectorXs& weights, const Scalar delta = Scalar(1.))
62 : Base(weights.size()), weights_(weights), delta_(delta) {
63 check_weights(weights_);
64 if (delta_ <= Scalar(0.)) {
65 throw_pretty(
66 "Invalid argument: delta should be a strictly positive value");
67 }
68 }
70
77 virtual void calc(const std::shared_ptr<ActivationDataAbstract>& data,
78 const Eigen::Ref<const VectorXs>& r) override {
79 if (static_cast<std::size_t>(r.size()) != nr_) {
80 throw_pretty(
81 "Invalid argument: " << "r has wrong dimension (it should be " +
82 std::to_string(nr_) + ")");
83 }
84 std::shared_ptr<Data> d = std::static_pointer_cast<Data>(data);
85
86 d->a = (r.array().square() + delta_ * delta_).sqrt().matrix();
87 data->a_value =
88 delta_ *
89 (weights_.array() * r.array().square() / (d->a.array() + delta_)).sum();
90 }
91
98 virtual void calcDiff(const std::shared_ptr<ActivationDataAbstract>& data,
99 const Eigen::Ref<const VectorXs>& r) override {
100 if (static_cast<std::size_t>(r.size()) != nr_) {
101 throw_pretty(
102 "Invalid argument: " << "r has wrong dimension (it should be " +
103 std::to_string(nr_) + ")");
104 }
105 std::shared_ptr<Data> d = std::static_pointer_cast<Data>(data);
106 const VectorXs a_inv = d->a.cwiseInverse();
107 data->Ar = delta_ * weights_.cwiseProduct(r).cwiseProduct(a_inv);
108 data->Arr.diagonal() =
109 delta_ * delta_ * delta_ *
110 weights_.cwiseProduct(a_inv.cwiseProduct(a_inv).cwiseProduct(a_inv));
111 }
112
118 virtual std::shared_ptr<ActivationDataAbstract> createData() override {
119 return std::allocate_shared<Data>(Eigen::aligned_allocator<Data>(), this);
120 }
121
122 template <typename NewScalar>
125 return ReturnType(weights_.template cast<NewScalar>(),
126 scalar_cast<NewScalar>(delta_));
127 }
128
129 const VectorXs& get_weights() const { return weights_; }
130 Scalar get_delta() const { return delta_; }
131
132 void set_weights(const VectorXs& weights) {
133 if (weights.size() != weights_.size()) {
134 throw_pretty("Invalid argument: "
135 << "weight vector has wrong dimension (it should be " +
136 std::to_string(weights_.size()) + ")");
137 }
138 check_weights(weights);
139 weights_ = weights;
140 }
141
147 virtual void print(std::ostream& os) const override {
148 os << "ActivationModelWeightedSmooth1Norm {nr=" << nr_
149 << ", delta=" << delta_ << "}";
150 }
151
152 protected:
153 using Base::nr_;
154
155 private:
156 static void check_weights(const VectorXs& weights) {
157 for (Eigen::Index i = 0; i < weights.size(); ++i) {
158 if (weights[i] < Scalar(0.)) {
159 throw_pretty(
160 "Invalid argument: weights should contain nonnegative values");
161 }
162 }
163 }
164
165 VectorXs weights_;
166 Scalar delta_;
167};
168
169template <typename _Scalar>
170struct ActivationDataWeightedSmooth1NormTpl
171 : public ActivationDataAbstractTpl<_Scalar> {
172 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
173
174 typedef _Scalar Scalar;
175 typedef ActivationDataAbstractTpl<Scalar> Base;
176 typedef MathBaseTpl<Scalar> MathBase;
177 typedef typename MathBase::VectorXs VectorXs;
178
179 template <typename Activation>
180 explicit ActivationDataWeightedSmooth1NormTpl(Activation* const activation)
181 : Base(activation), a(VectorXs::Zero(activation->get_nr())) {}
182 virtual ~ActivationDataWeightedSmooth1NormTpl() = default;
183
184 VectorXs a;
185
186 using Base::a_value;
187 using Base::Ar;
188 using Base::Arr;
189};
190
191} // namespace crocoddyl
192
193CROCODDYL_DECLARE_EXTERN_TEMPLATE_CLASS(
195CROCODDYL_DECLARE_EXTERN_TEMPLATE_STRUCT(
197
198#endif // CROCODDYL_CORE_ACTIVATIONS_WEIGHTED_SMOOTH_1NORM_HPP_
virtual void calcDiff(const std::shared_ptr< ActivationDataAbstract > &data, const Eigen::Ref< const VectorXs > &r) override
Compute the activation derivatives.
ActivationModelWeightedSmooth1NormTpl(const VectorXs &weights, const Scalar delta=Scalar(1.))
Initialize the weighted smooth-1norm activation model.
virtual std::shared_ptr< ActivationDataAbstract > createData() override
Create the weighted smooth-1norm activation data.
virtual void calc(const std::shared_ptr< ActivationDataAbstract > &data, const Eigen::Ref< const VectorXs > &r) override
Compute the weighted smooth-1norm activation.
virtual void print(std::ostream &os) const override
Print relevant information of the weighted smooth-1norm model.