Line data Source code
1 : #pragma once 2 : 3 : #include "Residual.h" 4 : #include <optional> 5 : 6 : namespace elsa 7 : { 8 : /** 9 : * @brief Class representing a linear residual, i.e. Ax - b with operator A and vectors x, b. 10 : * 11 : * @author Matthias Wieczorek - initial code 12 : * @author Tobias Lasser - modularization, modernization 13 : * 14 : * @tparam data_t data type for the domain and range of the operator, default to real_t 15 : * 16 : * A linear residual is a vector-valued mapping \f$ \mathbb{R}^n\to\mathbb{R}^m \f$, namely 17 : * \f$ x \mapsto Ax - b \f$, where A is a LinearOperator, b a constant data vector 18 : * (DataContainer) and x a variable (DataContainer). This linear residual can be used as input 19 : * to a Functional. 20 : */ 21 : template <typename data_t = real_t> 22 : class LinearResidual : public Residual<data_t> 23 : { 24 : public: 25 : /** 26 : * @brief Constructor for a trivial residual \f$ x \mapsto x \f$ 27 : * 28 : * @param[in] descriptor describing the domain = range of the residual 29 : */ 30 : explicit LinearResidual(const DataDescriptor& descriptor); 31 : 32 : /** 33 : * @brief Constructor for a simple residual \f$ x \mapsto x - b \f$ 34 : * 35 : * @param[in] b a vector (DataContainer) that will be subtracted from x 36 : */ 37 : explicit LinearResidual(const DataContainer<data_t>& b); 38 : 39 : /** @brief Constructor for a residual \f$ x \mapsto Ax \f$ 40 : * 41 : * @param[in] A a LinearOperator 42 : */ 43 : explicit LinearResidual(const LinearOperator<data_t>& A); 44 : 45 : /** 46 : * @brief Constructor for a residual \f$ x \mapsto Ax - b \f$ 47 : * 48 : * @param[in] A a LinearOperator 49 : * @param[in] b a vector (DataContainer) 50 : */ 51 : LinearResidual(const LinearOperator<data_t>& A, const DataContainer<data_t>& b); 52 : 53 : /// make copy constructor deletion explicit 54 : LinearResidual(const LinearResidual<data_t>&) = delete; 55 : 56 : /// default destructor 57 3884 : ~LinearResidual() override = default; 58 : 59 : /// return true if the residual has an operator A 60 : bool hasOperator() const; 61 : 62 : /// return true if the residual has a data vector b 63 : bool hasDataVector() const; 64 : 65 : /// return the operator A (throws if the residual has none) 66 : const LinearOperator<data_t>& getOperator() const; 67 : 68 : /// return the data vector b (throws if the residual has none) 69 : const DataContainer<data_t>& getDataVector() const; 70 : 71 : protected: 72 : /// implement the polymorphic clone operation 73 : LinearResidual<data_t>* cloneImpl() const override; 74 : 75 : /// implement the polymorphic comparison operation 76 : bool isEqual(const Residual<data_t>& other) const override; 77 : 78 : /// the evaluate method, evaluating the residual at x and placing the value in result 79 : void evaluateImpl(const DataContainer<data_t>& x, 80 : DataContainer<data_t>& result) const override; 81 : 82 : /** 83 : * @brief return the Jacobian (first derivative) of the linear residual at x. 84 : * 85 : * @param x input DataContainer (in the domain of the residual) 86 : * 87 : * @returns a LinearOperator (the Jacobian) 88 : * 89 : * If A is set, then the Jacobian is A and this returns a copy of A. 90 : * If A is not set, then an Identity operator is returned. 91 : */ 92 : LinearOperator<data_t> getJacobianImpl(const DataContainer<data_t>& x) override; 93 : 94 : private: 95 : /// the operator A, nullptr implies no operator present 96 : std::unique_ptr<LinearOperator<data_t>> _operator{}; 97 : 98 : /// optional data vector b 99 : std::optional<const DataContainer<data_t>> _dataVector{}; 100 : }; 101 : 102 : } // namespace elsa