LCOV - code coverage report
Current view: top level - elsa/functionals - ConstantFunctional.h (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 2 2 100.0 %
Date: 2024-05-16 04:22:26 Functions: 8 8 100.0 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include "DataContainer.h"
       4             : #include "DataDescriptor.h"
       5             : #include "Functional.h"
       6             : 
       7             : namespace elsa
       8             : {
       9             :     /// @brief Constant functional. This functinoal maps all input values to a constant scalar
      10             :     /// value.
      11             :     template <typename data_t = real_t>
      12             :     class ConstantFunctional : public Functional<data_t>
      13             :     {
      14             :     public:
      15             :         /// @brief Constructor for the constant functional, mapping domain vector to a scalar
      16             :         /// (without a residual)
      17             :         ConstantFunctional(const DataDescriptor& descriptor, SelfType_t<data_t> constant);
      18             : 
      19             :         /// make copy constructor deletion explicit
      20             :         ConstantFunctional(const ConstantFunctional<data_t>&) = delete;
      21             : 
      22             :         /// default destructor
      23         112 :         ~ConstantFunctional() override = default;
      24             : 
      25             :         bool isDifferentiable() const override;
      26             : 
      27             :         bool isProxFriendly() const override;
      28             : 
      29             :         /// Return the constant of the functional
      30             :         data_t getConstant() const;
      31             : 
      32             :         /// The convex conjugate for the constant or zero functional is
      33             :         /// @f[
      34             :         /// f^*(x)
      35             :         /// =
      36             :         /// \begin{cases}
      37             :         ///     -c, & \text{if } x = 0 \\ \infty, & \text{otherwise}
      38             :         /// \end{cases}
      39             :         /// @f]
      40             :         /// However, in algorithms like PDHG, this usually results in `inf` values,
      41             :         /// which is not desirable. Hence, the following penalisation is used:
      42             :         /// @f[
      43             :         /// f^*(x) = \sum \max(x, 0)
      44             :         /// @f]
      45             :         data_t convexConjugate(const DataContainer<data_t>& x) const override;
      46             : 
      47             :         /// The proximal for any constant function is simply the identity
      48             :         DataContainer<data_t> proximal(const DataContainer<data_t>& v,
      49             :                                        [[maybe_unused]] SelfType_t<data_t> t) const override;
      50             : 
      51             :         /// The proximal for any constant function is simply the identity
      52             :         void proximal(const DataContainer<data_t>& v, [[maybe_unused]] SelfType_t<data_t> t,
      53             :                       DataContainer<data_t>& out) const override;
      54             : 
      55             :     protected:
      56             :         /// Return the constant value
      57             :         data_t evaluateImpl(const DataContainer<data_t>& Rx) const override;
      58             : 
      59             :         /// The gradient operator is the ZeroOperator, hence set Rx to 0
      60             :         void getGradientImpl(const DataContainer<data_t>& Rx,
      61             :                              DataContainer<data_t>& out) const override;
      62             : 
      63             :         /// There does not exist a hessian, this will throw if called
      64             :         LinearOperator<data_t> getHessianImpl(const DataContainer<data_t>& Rx) const override;
      65             : 
      66             :         /// implement the polymorphic clone operation
      67             :         ConstantFunctional<data_t>* cloneImpl() const override;
      68             : 
      69             :         /// implement the polymorphic comparison operation
      70             :         bool isEqual(const Functional<data_t>& other) const override;
      71             : 
      72             :     private:
      73             :         data_t constant_;
      74             :     };
      75             : 
      76             :     /// @brief Zero functional. This functinoal maps all input values to a zero
      77             :     template <typename data_t = real_t>
      78             :     class ZeroFunctional : public Functional<data_t>
      79             :     {
      80             :     public:
      81             :         /// @brief Constructor for the zero functional, mapping domain vector to a scalar (without
      82             :         /// a residual)
      83             :         ZeroFunctional(const DataDescriptor& descriptor);
      84             : 
      85             :         /// make copy constructor deletion explicit
      86             :         ZeroFunctional(const ConstantFunctional<data_t>&) = delete;
      87             : 
      88             :         /// default destructor
      89          80 :         ~ZeroFunctional() override = default;
      90             : 
      91             :         bool isDifferentiable() const override;
      92             : 
      93             :         bool isProxFriendly() const override;
      94             : 
      95             :         /// The convex conjugate for the constant or zero functional is
      96             :         /// @f[
      97             :         /// f^*(x)
      98             :         /// =
      99             :         /// \begin{cases}
     100             :         ///     -c, & \text{if } x = 0 \\ \infty, & \text{otherwise}
     101             :         /// \end{cases}
     102             :         /// @f]
     103             :         /// However, in algorithms like PDHG, this usually results in `inf` values,
     104             :         /// which is not desirable. Hence, the following penalisation is used:
     105             :         /// @f[
     106             :         /// f^*(x) = \sum \max(x, 0)
     107             :         /// @f]
     108             :         data_t convexConjugate(const DataContainer<data_t>& x) const override;
     109             : 
     110             :         /// The proximal for any constant function is simply the identity
     111             :         DataContainer<data_t> proximal(const DataContainer<data_t>& v,
     112             :                                        [[maybe_unused]] SelfType_t<data_t> t) const override;
     113             : 
     114             :         /// The proximal for any constant function is simply the identity
     115             :         void proximal(const DataContainer<data_t>& v, [[maybe_unused]] SelfType_t<data_t> t,
     116             :                       DataContainer<data_t>& out) const override;
     117             : 
     118             :     protected:
     119             :         /// Return the constant value
     120             :         data_t evaluateImpl(const DataContainer<data_t>& Rx) const override;
     121             : 
     122             :         /// The gradient operator is the ZeroOperator, hence set Rx to 0
     123             :         void getGradientImpl(const DataContainer<data_t>& Rx,
     124             :                              DataContainer<data_t>& out) const override;
     125             : 
     126             :         /// There does not exist a hessian, this will throw if called
     127             :         LinearOperator<data_t> getHessianImpl(const DataContainer<data_t>& Rx) const override;
     128             : 
     129             :         /// implement the polymorphic clone operation
     130             :         ZeroFunctional<data_t>* cloneImpl() const override;
     131             : 
     132             :         /// implement the polymorphic comparison operation
     133             :         bool isEqual(const Functional<data_t>& other) const override;
     134             :     };
     135             : 
     136             : } // namespace elsa

Generated by: LCOV version 1.14