Line data Source code
1 : #pragma once 2 : 3 : #include "DataContainer.h" 4 : #include "DataDescriptor.h" 5 : #include "Functional.h" 6 : #include <limits> 7 : 8 : namespace elsa 9 : { 10 : /// @brief Indicator function for some box shaped set. 11 : /// 12 : /// The indicator function with the lower bound \f$a\f$ and the upper bound 13 : /// \f$b\f$ is given by: 14 : /// \f[ 15 : /// f(x) = 16 : /// \begin{cases} 17 : /// 0 & \text{if } a \leq x \leq b \text{ everywhere}, \\ \infty & \text{else} 18 : /// \end{cases} 19 : /// \f] 20 : template <class data_t> 21 : class IndicatorBox final : public Functional<data_t> 22 : { 23 : public: 24 : /// Construct indicator function with \f$-\infty\f$ and \f$\infty\f$ bounds 25 : explicit IndicatorBox(const DataDescriptor& desc); 26 : 27 : /// Construct indicator function with given bounds 28 : IndicatorBox(const DataDescriptor& desc, SelfType_t<data_t> lower, 29 : SelfType_t<data_t> upper); 30 : 31 8 : bool isProxFriendly() const override { return true; } 32 : 33 : data_t convexConjugate(const DataContainer<data_t>& x) const override; 34 : 35 : DataContainer<data_t> proximal(const DataContainer<data_t>& v, 36 : [[maybe_unused]] SelfType_t<data_t> t) const override; 37 : 38 : void proximal(const DataContainer<data_t>& v, [[maybe_unused]] SelfType_t<data_t> t, 39 : DataContainer<data_t>& out) const override; 40 : 41 : private: 42 : /// Evaluate the functional 43 : data_t evaluateImpl(const DataContainer<data_t>& Rx) const override; 44 : 45 : /// The gradient functions throws, the indicator function has no gradient 46 : void getGradientImpl(const DataContainer<data_t>& Rx, 47 : DataContainer<data_t>&) const override; 48 : 49 : /// The gradient functions throws, the indicator function has no hessian 50 : LinearOperator<data_t> getHessianImpl(const DataContainer<data_t>& Rx) const override; 51 : 52 : /// Implementation of polymorphic clone 53 : IndicatorBox<data_t>* cloneImpl() const override; 54 : 55 : /// Implementation of polymorphic equality 56 : bool isEqual(const Functional<data_t>& other) const override; 57 : 58 : /// Lower bound 59 : data_t lower_ = -std::numeric_limits<data_t>::infinity(); 60 : 61 : /// Upper bound 62 : data_t upper_ = std::numeric_limits<data_t>::infinity(); 63 : }; 64 : 65 : /// @brief Indicator function for the set of non-negative numbers. 66 : /// 67 : /// The nonnegativity indicator for the set of non-negative numbers is defined as: 68 : /// \f[ 69 : /// f(x) = 70 : /// \begin{cases} 71 : /// 0 & \text{if } 0 \leq x \text{ everywhere}, \\ \infty & \text{else} 72 : /// \end{cases} 73 : /// \f] 74 : template <class data_t> 75 : class IndicatorNonNegativity final : public Functional<data_t> 76 : { 77 : public: 78 : /// Construct non-negativity indicator functional 79 : explicit IndicatorNonNegativity(const DataDescriptor& desc); 80 : 81 12 : bool isProxFriendly() const override { return true; } 82 : 83 : DataContainer<data_t> proximal(const DataContainer<data_t>& v, 84 : [[maybe_unused]] SelfType_t<data_t> t) const override; 85 : 86 : void proximal(const DataContainer<data_t>& v, [[maybe_unused]] SelfType_t<data_t> t, 87 : DataContainer<data_t>& out) const override; 88 : 89 : data_t convexConjugate(const DataContainer<data_t>& x) const override; 90 : 91 : private: 92 : /// Evaluate the functional 93 : data_t evaluateImpl(const DataContainer<data_t>& Rx) const override; 94 : 95 : /// The gradient functions throws, the indicator function has no gradient 96 : void getGradientImpl(const DataContainer<data_t>& Rx, 97 : DataContainer<data_t>&) const override; 98 : 99 : /// The gradient functions throws, the indicator function has no hessian 100 : LinearOperator<data_t> getHessianImpl(const DataContainer<data_t>& Rx) const override; 101 : 102 : /// Implementation of polymorphic clone 103 : IndicatorNonNegativity<data_t>* cloneImpl() const override; 104 : 105 : /// Implementation of polymorphic equality 106 : bool isEqual(const Functional<data_t>& other) const override; 107 : }; 108 : } // namespace elsa