Line data Source code
1 : #pragma once 2 : 3 : #include "Problem.h" 4 : #include "Scaling.h" 5 : #include "LinearResidual.h" 6 : 7 : namespace elsa 8 : { 9 : /** 10 : * @brief Class representing a weighted least squares problem. 11 : * 12 : * @author Jakob Vogel - initial code 13 : * @author Matthias Wieczorek - rewrite 14 : * @author Tobias Lasser - another rewrite, modernization 15 : * @author Nikola Dinev - added conversion constructor 16 : * 17 : * @tparam data_t data type for the domain and range of the problem, defaulting to real_t 18 : * 19 : * This class represents a weighted least squares optimization problem, i.e. 20 : * \f$ \argmin_x \frac{1}{2} \| Ax - b \|_{W,2}^2 \f$, where \f$ W \f$ is a weighting (scaling) 21 : * operator, \f$ A \f$ is a linear operator and \f$ b \f$ is a data vector. 22 : */ 23 : template <typename data_t = real_t> 24 : class WLSProblem : public Problem<data_t> 25 : { 26 : public: 27 : /** 28 : * @brief Constructor for the wls problem, accepting W, A, b, and an initial guess x0 29 : * 30 : * @param[in] W scaling operator for weighting 31 : * @param[in] A linear operator 32 : * @param[in] b data vector 33 : * @param[in] x0 initial value for the current estimated solution 34 : * @param[in] lipschitzConstant if non-null the known lipschitz constant of the 35 : * problem. If null the lipschitz constant will be computed using power-iteration. Useful in 36 : * cases where the numerical approximation is not accurate and the constant is known. 37 : */ 38 : WLSProblem(const Scaling<data_t>& W, const LinearOperator<data_t>& A, 39 : const DataContainer<data_t>& b, const DataContainer<data_t>& x0, 40 : std::optional<data_t> lipschitzConstant = {}); 41 : 42 : /** 43 : * @brief Constructor for the wls problem, accepting W, A, and b 44 : * 45 : * @param[in] W scaling operator for weighting 46 : * @param[in] A linear operator 47 : * @param[in] b data vector 48 : * @param[in] lipschitzConstant if non-null the known lipschitz constant of the 49 : * problem. If null the lipschitz constant will be computed using power-iteration. Useful in 50 : * cases where the numerical approximation is not accurate and the constant is known. 51 : */ 52 : WLSProblem(const Scaling<data_t>& W, const LinearOperator<data_t>& A, 53 : const DataContainer<data_t>& b, std::optional<data_t> lipschitzConstant = {}); 54 : 55 : /** 56 : * @brief Constructor for the (w)ls problem, accepting A, b, and an initial guess x0 (no 57 : * weights) 58 : * 59 : * @param[in] A linear operator 60 : * @param[in] b data vector 61 : * @param[in] x0 initial value for the current estimated solution 62 : * @param[in] lipschitzConstant if non-null the known lipschitz constant of the 63 : * problem. If null the lipschitz constant will be computed using power-iteration. Useful in 64 : * cases where the numerical approximation is not accurate and the constant is known. 65 : */ 66 : WLSProblem(const LinearOperator<data_t>& A, const DataContainer<data_t>& b, 67 : const DataContainer<data_t>& x0, std::optional<data_t> lipschitzConstant = {}); 68 : 69 : /** 70 : * @brief Constructor for the (w)ls problem, accepting A and b (no weights) 71 : * 72 : * @param[in] A linear operator 73 : * @param[in] b data vector 74 : * @param[in] lipschitzConstant if non-null the known lipschitz constant of the 75 : * problem. If null the lipschitz constant will be computed using power-iteration. Useful in 76 : * cases where the numerical approximation is not accurate and the constant is known. 77 : */ 78 : WLSProblem(const LinearOperator<data_t>& A, const DataContainer<data_t>& b, 79 : std::optional<data_t> lipschitzConstant = {}); 80 : 81 : /** 82 : * @brief Constructor for converting a general optimization problem to a WLS problem 83 : * 84 : * @param[in] problem the problem to be converted 85 : * 86 : * Only problems that consist exclusively of (Weighted)L2NormPow2 terms can be converted. 87 : * The (Weighted)L2NormPow2 should be acting on a LinearResidual. 88 : * 89 : * Acts as a copy constructor if the supplied optimization problem is a quadric problem. 90 : */ 91 : explicit WLSProblem(const Problem<data_t>& problem); 92 : 93 : /// default destructor 94 304 : ~WLSProblem() override = default; 95 : 96 : protected: 97 : /// implement the polymorphic clone operation 98 : WLSProblem<data_t>* cloneImpl() const override; 99 : 100 : private: 101 : /// converts an optimization problem to a (Weighted)L2NormPow2 functional 102 : static std::unique_ptr<Functional<data_t>> wlsFromProblem(const Problem<data_t>& problem); 103 : }; 104 : } // namespace elsa