LCOV - code coverage report
Current view: top level - elsa/solvers - LandweberIteration.cpp (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 30 38 78.9 %
Date: 2024-12-21 07:37:52 Functions: 12 16 75.0 %

          Line data    Source code
       1             : #include "LandweberIteration.h"
       2             : #include "DataContainer.h"
       3             : #include "Functional.h"
       4             : #include "LinearOperator.h"
       5             : #include "Logger.h"
       6             : #include "TypeCasts.hpp"
       7             : #include "PowerIterations.h"
       8             : #include <iostream>
       9             : 
      10             : namespace elsa
      11             : {
      12             :     template <typename data_t>
      13             :     LandweberIteration<data_t>::LandweberIteration(const LinearOperator<data_t>& A,
      14             :                                                    const DataContainer<data_t>& b, data_t stepSize)
      15             :         : Solver<data_t>(), A_(A.clone()), b_(b), residual_(emptylike(b)), stepSize_{stepSize}
      16           8 :     {
      17           8 :     }
      18             : 
      19             :     template <typename data_t>
      20             :     LandweberIteration<data_t>::LandweberIteration(const LinearOperator<data_t>& A,
      21             :                                                    const DataContainer<data_t>& b)
      22             :         : Solver<data_t>(), A_(A.clone()), b_(b), residual_(emptylike(b))
      23           0 :     {
      24           0 :     }
      25             : 
      26             :     template <typename data_t>
      27             :     DataContainer<data_t> LandweberIteration<data_t>::setup(std::optional<DataContainer<data_t>> x0)
      28           4 :     {
      29           4 :         auto x = extract_or(x0, A_->getDomainDescriptor());
      30             : 
      31           4 :         if (!tam_) {
      32           4 :             tam_ = setupOperators(*A_);
      33           4 :         }
      34             : 
      35           4 :         if (!stepSize_.isInitialized()) {
      36             :             // Choose step length to be just below \f$\frac{2}{\sigma^2}\f$, where \f$\sigma\f$
      37             :             // is the largest eigenvalue of \f$T * A^T * M * A\f$. This is computed using the power
      38             :             // iterations.
      39           0 :             auto Anorm = powerIterations(*tam_ * *A_);
      40           0 :             stepSize_ = 0.9 * (2. / Anorm);
      41           0 :         }
      42             : 
      43           4 :         Logger::get("LandweberIterations")->info("Using Steplength: {}", *stepSize_);
      44             : 
      45             :         // setup done!
      46           4 :         this->configured_ = true;
      47             : 
      48           4 :         return x;
      49           4 :     }
      50             : 
      51             :     template <typename data_t>
      52             :     DataContainer<data_t> LandweberIteration<data_t>::step(DataContainer<data_t> x)
      53           4 :     {
      54             :         // Compute Ax - b memory efficient
      55           4 :         A_->apply(x, residual_);
      56           4 :         residual_ -= b_;
      57             : 
      58           4 :         x -= (*stepSize_) * tam_->apply(residual_);
      59             : 
      60           4 :         projection_(x);
      61             : 
      62           4 :         return x;
      63           4 :     }
      64             : 
      65             :     template <typename data_t>
      66             :     std::string LandweberIteration<data_t>::formatHeader() const
      67           4 :     {
      68           4 :         return fmt::format("{:^12} | {:^12} |", "x norm", "Residual");
      69           4 :     }
      70             : 
      71             :     template <typename data_t>
      72             :     std::string LandweberIteration<data_t>::formatStep(const DataContainer<data_t>& x) const
      73           4 :     {
      74           4 :         return fmt::format("{:>12.5f} | {:>12.5f} |", x.l2Norm(), residual_.l2Norm());
      75           4 :     }
      76             : 
      77             :     template <typename data_t>
      78             :     bool LandweberIteration<data_t>::isEqual(const Solver<data_t>& other) const
      79           4 :     {
      80           4 :         auto landweber = downcast_safe<LandweberIteration<data_t>>(&other);
      81           4 :         return landweber && *A_ == *landweber->A_ && b_ == landweber->b_
      82           4 :                && stepSize_ == landweber->stepSize_;
      83           4 :     }
      84             : 
      85             :     template <class data_t>
      86             :     void LandweberIteration<data_t>::setProjection(
      87             :         const std::function<void(DataContainer<data_t>&)> projection)
      88           0 :     {
      89           0 :         projection_ = projection;
      90           0 :     }
      91             : 
      92             :     // ------------------------------------------
      93             :     // explicit template instantiation
      94             :     template class LandweberIteration<float>;
      95             :     template class LandweberIteration<double>;
      96             : } // namespace elsa

Generated by: LCOV version 1.14