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