LCOV - code coverage report
Current view: top level - elsa/problems/tests - test_WLSProblem.cpp (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 338 338 100.0 %
Date: 2022-08-25 03:05:39 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file test_WLSProblem.cpp
       3             :  *
       4             :  * @brief Tests for the WLSProblem class
       5             :  *
       6             :  * @author Matthias Wieczorek - initial code
       7             :  * @author Maximilian Hornung - modularization
       8             :  * @author David Frank - rewrite
       9             :  * @author Tobias Lasser - rewrite, modernization
      10             :  * @author Nikola Dinev - added tests for conversion constructor
      11             :  */
      12             : 
      13             : #include "doctest/doctest.h"
      14             : 
      15             : #include "WLSProblem.h"
      16             : #include "Identity.h"
      17             : #include "Scaling.h"
      18             : #include "L2NormPow2.h"
      19             : #include "WeightedL2NormPow2.h"
      20             : #include "Quadric.h"
      21             : #include "TikhonovProblem.h"
      22             : #include "BlockLinearOperator.h"
      23             : #include "RandomBlocksDescriptor.h"
      24             : #include "VolumeDescriptor.h"
      25             : #include "testHelpers.h"
      26             : 
      27             : using namespace elsa;
      28             : using namespace doctest;
      29             : 
      30             : TEST_SUITE_BEGIN("problems");
      31             : 
      32             : TEST_CASE_TEMPLATE("WLSProblems: Testing with operator and data", TestType, float, double)
      33           8 : {
      34           8 :     GIVEN("the operator and data")
      35           8 :     {
      36           8 :         IndexVector_t numCoeff(2);
      37           8 :         numCoeff << 7, 13;
      38           8 :         VolumeDescriptor dd(numCoeff);
      39             : 
      40           8 :         Eigen::Matrix<TestType, Eigen::Dynamic, 1> bVec(dd.getNumberOfCoefficients());
      41           8 :         bVec.setRandom();
      42           8 :         DataContainer<TestType> dcB(dd, bVec);
      43             : 
      44           8 :         Identity<TestType> idOp(dd);
      45             : 
      46           8 :         WHEN("setting up a ls problem without x0")
      47           8 :         {
      48           4 :             WLSProblem<TestType> prob(idOp, dcB);
      49             : 
      50           4 :             THEN("the clone works correctly")
      51           4 :             {
      52           2 :                 auto probClone = prob.clone();
      53             : 
      54           2 :                 REQUIRE_NE(probClone.get(), &prob);
      55           2 :                 REQUIRE_EQ(*probClone, prob);
      56           2 :             }
      57             : 
      58           4 :             THEN("the problem behaves as expected")
      59           4 :             {
      60           2 :                 DataContainer<TestType> dcZero(dd);
      61           2 :                 dcZero = 0;
      62           2 :                 REQUIRE_UNARY(isApprox(prob.getCurrentSolution(), dcZero));
      63             : 
      64           2 :                 REQUIRE_UNARY(
      65           2 :                     checkApproxEq(prob.evaluate(), as<TestType>(0.5) * bVec.squaredNorm()));
      66           2 :                 REQUIRE_UNARY(
      67           2 :                     checkApproxEq(prob.getGradient(), static_cast<TestType>(-1.0f) * dcB));
      68             : 
      69           2 :                 auto hessian = prob.getHessian();
      70           2 :                 REQUIRE_UNARY(isApprox(hessian.apply(dcB), dcB));
      71           2 :             }
      72           4 :         }
      73             : 
      74           8 :         WHEN("setting up a ls problem with x0")
      75           8 :         {
      76           4 :             Eigen::Matrix<TestType, Eigen::Dynamic, 1> x0Vec(dd.getNumberOfCoefficients());
      77           4 :             x0Vec.setRandom();
      78           4 :             DataContainer<TestType> dcX0(dd, x0Vec);
      79             : 
      80           4 :             WLSProblem<TestType> prob(idOp, dcB, dcX0);
      81             : 
      82           4 :             THEN("the clone works correctly")
      83           4 :             {
      84           2 :                 auto probClone = prob.clone();
      85             : 
      86           2 :                 REQUIRE_NE(probClone.get(), &prob);
      87           2 :                 REQUIRE_EQ(*probClone, prob);
      88           2 :             }
      89             : 
      90           4 :             THEN("the problem behaves as expected")
      91           4 :             {
      92             : 
      93           2 :                 REQUIRE_UNARY(isApprox(prob.getCurrentSolution(), dcX0));
      94             : 
      95           2 :                 REQUIRE_UNARY(checkApproxEq(prob.evaluate(),
      96           2 :                                             as<TestType>(0.5) * (x0Vec - bVec).squaredNorm()));
      97           2 :                 REQUIRE_UNARY(isApprox(prob.getGradient(), dcX0 - dcB));
      98             : 
      99           2 :                 auto hessian = prob.getHessian();
     100           2 :                 REQUIRE_UNARY(isApprox(hessian.apply(dcB), dcB));
     101           2 :             }
     102           4 :         }
     103           8 :     }
     104           8 : }
     105             : 
     106             : TEST_CASE_TEMPLATE("WLSProblems: Testing with weights, operator and data", TestType, float, double)
     107           8 : {
     108           8 :     GIVEN("weights, operator and data")
     109           8 :     {
     110           8 :         IndexVector_t numCoeff(3);
     111           8 :         numCoeff << 7, 13, 17;
     112           8 :         VolumeDescriptor dd(numCoeff);
     113             : 
     114           8 :         Eigen::Matrix<TestType, Eigen::Dynamic, 1> bVec(dd.getNumberOfCoefficients());
     115           8 :         bVec.setRandom();
     116           8 :         DataContainer<TestType> dcB(dd, bVec);
     117             : 
     118           8 :         Identity<TestType> idOp(dd);
     119             : 
     120           8 :         Eigen::Matrix<TestType, Eigen::Dynamic, 1> weightsVec(dd.getNumberOfCoefficients());
     121           8 :         weightsVec.setRandom();
     122           8 :         DataContainer dcWeights(dd, weightsVec);
     123           8 :         Scaling scaleOp(dd, dcWeights);
     124             : 
     125           8 :         WHEN("setting up a wls problem without x0")
     126           8 :         {
     127           4 :             WLSProblem<TestType> prob(scaleOp, idOp, dcB);
     128             : 
     129           4 :             THEN("the clone works correctly")
     130           4 :             {
     131           2 :                 auto probClone = prob.clone();
     132             : 
     133           2 :                 REQUIRE_NE(probClone.get(), &prob);
     134           2 :                 REQUIRE_EQ(*probClone, prob);
     135           2 :             }
     136             : 
     137           4 :             THEN("the problem behaves as expected")
     138           4 :             {
     139           2 :                 DataContainer<TestType> dcZero(dd);
     140           2 :                 dcZero = 0;
     141           2 :                 REQUIRE_UNARY(isApprox(prob.getCurrentSolution(), dcZero));
     142             : 
     143           2 :                 REQUIRE_UNARY(checkApproxEq(
     144           2 :                     prob.evaluate(),
     145           2 :                     as<TestType>(0.5) * bVec.dot((weightsVec.array() * bVec.array()).matrix())));
     146           2 :                 DataContainer<TestType> tmpDc = as<TestType>(-1) * dcWeights * dcB;
     147           2 :                 REQUIRE_UNARY(isApprox(prob.getGradient(), tmpDc));
     148             : 
     149           2 :                 auto hessian = prob.getHessian();
     150           2 :                 REQUIRE_UNARY(isApprox(hessian.apply(dcB), dcWeights * dcB));
     151           2 :             }
     152           4 :         }
     153             : 
     154           8 :         WHEN("setting up a wls problem with x0")
     155           8 :         {
     156           4 :             Eigen::Matrix<TestType, Eigen::Dynamic, 1> x0Vec(dd.getNumberOfCoefficients());
     157           4 :             x0Vec.setRandom();
     158           4 :             DataContainer<TestType> dcX0(dd, x0Vec);
     159             : 
     160           4 :             WLSProblem<TestType> prob(scaleOp, idOp, dcB, dcX0);
     161             : 
     162           4 :             THEN("the clone works correctly")
     163           4 :             {
     164           2 :                 auto probClone = prob.clone();
     165             : 
     166           2 :                 REQUIRE_NE(probClone.get(), &prob);
     167           2 :                 REQUIRE_EQ(*probClone, prob);
     168           2 :             }
     169             : 
     170           4 :             THEN("the problem behaves as expected")
     171           4 :             {
     172           2 :                 DataContainer<TestType> dcZero(dd);
     173           2 :                 dcZero = 0;
     174           2 :                 REQUIRE_UNARY(isApprox(prob.getCurrentSolution(), dcX0));
     175             : 
     176           2 :                 REQUIRE_UNARY(checkApproxEq(
     177           2 :                     prob.evaluate(),
     178           2 :                     as<TestType>(0.5)
     179           2 :                         * (x0Vec - bVec)
     180           2 :                               .dot((weightsVec.array() * (x0Vec - bVec).array()).matrix())));
     181           2 :                 REQUIRE_UNARY(isApprox(prob.getGradient(), dcWeights * (dcX0 - dcB)));
     182             : 
     183           2 :                 auto hessian = prob.getHessian();
     184           2 :                 REQUIRE_UNARY(isApprox(hessian.apply(dcB), dcWeights * dcB));
     185           2 :             }
     186           4 :         }
     187           8 :     }
     188           8 : }
     189             : 
     190             : TEST_CASE_TEMPLATE("WLSProblems: Testing different optimization problems", TestType, float, double)
     191          18 : {
     192          18 :     GIVEN("an optimization problem with only a (w)ls data term")
     193          18 :     {
     194           2 :         VolumeDescriptor desc{IndexVector_t::Constant(1, 343)};
     195             : 
     196           2 :         Scaling<TestType> W{desc, static_cast<TestType>(3.0)};
     197             : 
     198           2 :         LinearResidual<TestType> residual{desc};
     199           2 :         L2NormPow2<TestType> func{residual};
     200           2 :         WeightedL2NormPow2<TestType> weightedFunc{residual, W};
     201           2 :         Problem<TestType> prob{func};
     202           2 :         Problem<TestType> weightedProb{weightedFunc};
     203             : 
     204           2 :         WHEN("converting to a wls problem")
     205           2 :         {
     206           2 :             WLSProblem<TestType> lsProb{prob};
     207           2 :             WLSProblem<TestType> wlsProb{weightedProb};
     208             : 
     209           2 :             THEN("only the type of the problem changes")
     210           2 :             {
     211           2 :                 REQUIRE_EQ(lsProb.getDataTerm(), prob.getDataTerm());
     212           2 :                 REQUIRE_EQ(lsProb.getRegularizationTerms(), prob.getRegularizationTerms());
     213           2 :                 REQUIRE_EQ(wlsProb.getDataTerm(), weightedProb.getDataTerm());
     214           2 :                 REQUIRE_EQ(wlsProb.getRegularizationTerms(), weightedProb.getRegularizationTerms());
     215           2 :             }
     216           2 :         }
     217           2 :     }
     218             : 
     219          18 :     GIVEN("an optimization problem with a non-(w)ls data term")
     220          18 :     {
     221           2 :         VolumeDescriptor desc{IndexVector_t::Constant(1, 343)};
     222             : 
     223           2 :         Quadric<TestType> quadric{desc};
     224           2 :         Problem prob{quadric};
     225             : 
     226           2 :         WHEN("converting to a WLSProblem")
     227           2 :         {
     228           2 :             THEN("an exception is thrown") { REQUIRE_THROWS(WLSProblem<TestType>{prob}); }
     229           2 :         }
     230           2 :     }
     231             : 
     232          18 :     GIVEN("an optimization problem with a non-(w)ls regularization term")
     233          18 :     {
     234           2 :         VolumeDescriptor desc{IndexVector_t::Constant(1, 343)};
     235             : 
     236           2 :         Quadric<TestType> quadric{desc};
     237           2 :         RegularizationTerm regTerm{static_cast<TestType>(5), quadric};
     238           2 :         Problem prob{L2NormPow2<TestType>{desc}, regTerm};
     239             : 
     240           2 :         WHEN("converting to a WLSProblem")
     241           2 :         {
     242           2 :             THEN("an exception is thrown") { REQUIRE_THROWS(WLSProblem<TestType>{prob}); }
     243           2 :         }
     244           2 :     }
     245             : 
     246          18 :     GIVEN("an optimization problem with a wls data term that has negative weighting factors")
     247          18 :     {
     248           4 :         VolumeDescriptor desc{IndexVector_t::Constant(1, 343)};
     249             : 
     250           4 :         Scaling<TestType> W1{desc, static_cast<TestType>(-3.0)};
     251             : 
     252           4 :         Eigen::Matrix<TestType, Eigen::Dynamic, 1> anisotropicW =
     253           4 :             Eigen::Matrix<TestType, Eigen::Dynamic, 1>::Constant(343, 1);
     254           4 :         anisotropicW[256] = -3.0;
     255             : 
     256           4 :         Scaling<TestType> W2{desc, DataContainer(desc, anisotropicW)};
     257             : 
     258           4 :         LinearResidual<TestType> residual{desc};
     259           4 :         WeightedL2NormPow2<TestType> weightedFunc1{residual, W1};
     260           4 :         WeightedL2NormPow2<TestType> weightedFunc2{residual, W2};
     261             : 
     262           4 :         WHEN("convering to a WLSProblem and no regularization terms are present")
     263           4 :         {
     264           2 :             Problem prob1{weightedFunc1};
     265           2 :             Problem prob2{weightedFunc2};
     266             : 
     267           2 :             WLSProblem converted1{prob1};
     268           2 :             WLSProblem converted2{prob2};
     269             : 
     270           2 :             THEN("only the type of the problem changes")
     271           2 :             {
     272           2 :                 REQUIRE_EQ(prob1.getDataTerm(), converted1.getDataTerm());
     273           2 :                 REQUIRE_EQ(prob1.getRegularizationTerms(), converted1.getRegularizationTerms());
     274           2 :                 REQUIRE_EQ(prob2.getDataTerm(), converted2.getDataTerm());
     275           2 :                 REQUIRE_EQ(prob2.getRegularizationTerms(), converted2.getRegularizationTerms());
     276           2 :             }
     277           2 :         }
     278             : 
     279           4 :         WHEN("convering to a WLSProblem and regularization terms are present")
     280           4 :         {
     281           2 :             RegularizationTerm regTerm{static_cast<TestType>(1.0), L2NormPow2<TestType>{desc}};
     282           2 :             Problem prob1{weightedFunc1, regTerm};
     283           2 :             Problem prob2{weightedFunc2, regTerm};
     284             : 
     285           2 :             THEN("an exception is thrown")
     286           2 :             {
     287           2 :                 REQUIRE_THROWS(WLSProblem{prob1});
     288           2 :                 REQUIRE_THROWS(WLSProblem{prob2});
     289           2 :             }
     290           2 :         }
     291           4 :     }
     292             : 
     293          18 :     GIVEN("an optimization problem with a (w)ls regularization term that has negative weighting "
     294          18 :           "factors")
     295          18 :     {
     296           2 :         VolumeDescriptor desc{IndexVector_t::Constant(1, 343)};
     297             : 
     298           2 :         Scaling<TestType> W1{desc, static_cast<TestType>(-3.0)};
     299             : 
     300           2 :         Eigen::Matrix<TestType, Eigen::Dynamic, 1> anisotropicW =
     301           2 :             Eigen::Matrix<TestType, Eigen::Dynamic, 1>::Constant(343, 1);
     302           2 :         anisotropicW[256] = -3.0;
     303             : 
     304           2 :         Scaling<TestType> W2{desc, DataContainer(desc, anisotropicW)};
     305             : 
     306           2 :         LinearResidual<TestType> residual{desc};
     307           2 :         WeightedL2NormPow2<TestType> weightedFunc1{residual, W1};
     308           2 :         WeightedL2NormPow2<TestType> weightedFunc2{residual, W2};
     309           2 :         L2NormPow2<TestType> nonWeightedFunc{desc};
     310             : 
     311           2 :         RegularizationTerm negWeights{static_cast<TestType>(1.0), weightedFunc1};
     312           2 :         RegularizationTerm mixedWeights{static_cast<TestType>(1.0), weightedFunc2};
     313           2 :         RegularizationTerm noWeightsNegLambda{static_cast<TestType>(-1.0), nonWeightedFunc};
     314           2 :         WHEN("convering to a WLSProblem")
     315           2 :         {
     316           2 :             Problem prob1{L2NormPow2<TestType>{desc}, negWeights};
     317           2 :             Problem prob2{L2NormPow2<TestType>{desc}, mixedWeights};
     318           2 :             Problem prob3{L2NormPow2<TestType>{desc}, noWeightsNegLambda};
     319             : 
     320           2 :             THEN("an exception is thrown")
     321           2 :             {
     322           2 :                 REQUIRE_THROWS(WLSProblem{prob1});
     323           2 :                 REQUIRE_THROWS(WLSProblem{prob2});
     324           2 :                 REQUIRE_THROWS(WLSProblem{prob3});
     325           2 :             }
     326           2 :         }
     327           2 :     }
     328             : 
     329          18 :     GIVEN("an OptimizationProblem with only (w)ls terms")
     330          18 :     {
     331           4 :         VolumeDescriptor desc{IndexVector_t::Constant(1, 343)};
     332           4 :         Eigen::Matrix<TestType, Eigen::Dynamic, 1> vec =
     333           4 :             Eigen::Matrix<TestType, Eigen::Dynamic, 1>::Random(343);
     334           4 :         DataContainer<TestType> b{desc, vec};
     335             : 
     336           4 :         Scaling<TestType> A{desc, static_cast<TestType>(2.0)};
     337             : 
     338           4 :         Scaling<TestType> isoW{desc, static_cast<TestType>(3.0)};
     339           4 :         Eigen::Matrix<TestType, Eigen::Dynamic, 1> vecW =
     340           4 :             Eigen::abs(Eigen::Matrix<TestType, Eigen::Dynamic, 1>::Random(343).array());
     341           4 :         DataContainer<TestType> dcW{desc, vecW};
     342           4 :         Scaling<TestType> nonIsoW{desc, dcW};
     343             : 
     344           4 :         std::vector<std::unique_ptr<Functional<TestType>>> dataTerms;
     345             : 
     346           4 :         dataTerms.push_back(std::make_unique<L2NormPow2<TestType>>(desc));
     347           4 :         dataTerms.push_back(std::make_unique<L2NormPow2<TestType>>(LinearResidual{b}));
     348           4 :         dataTerms.push_back(std::make_unique<L2NormPow2<TestType>>(LinearResidual{A}));
     349           4 :         dataTerms.push_back(std::make_unique<L2NormPow2<TestType>>(LinearResidual{A, b}));
     350           4 :         dataTerms.push_back(
     351           4 :             std::make_unique<WeightedL2NormPow2<TestType>>(LinearResidual{A, b}, isoW));
     352           4 :         dataTerms.push_back(
     353           4 :             std::make_unique<WeightedL2NormPow2<TestType>>(LinearResidual{A, b}, nonIsoW));
     354             : 
     355           4 :         Eigen::Matrix<TestType, Eigen::Dynamic, 1> regVec =
     356           4 :             Eigen::Matrix<TestType, Eigen::Dynamic, 1>::Random(343);
     357           4 :         DataContainer<TestType> bReg{desc, regVec};
     358             : 
     359           4 :         Scaling<TestType> AReg{desc, static_cast<TestType>(0.25)};
     360             : 
     361           4 :         Scaling<TestType> isoWReg{desc, static_cast<TestType>(1.5)};
     362           4 :         Eigen::Matrix<TestType, Eigen::Dynamic, 1> vecWReg =
     363           4 :             Eigen::abs(Eigen::Matrix<TestType, Eigen::Dynamic, 1>::Random(343).array());
     364           4 :         DataContainer<TestType> dcWReg{desc, vecWReg};
     365           4 :         Scaling<TestType> nonIsoWReg{desc, dcWReg};
     366             : 
     367           4 :         std::vector<std::unique_ptr<RegularizationTerm<TestType>>> regTerms;
     368           4 :         auto weight = static_cast<TestType>(0.5);
     369           4 :         regTerms.push_back(
     370           4 :             std::make_unique<RegularizationTerm<TestType>>(weight, L2NormPow2<TestType>{desc}));
     371           4 :         regTerms.push_back(std::make_unique<RegularizationTerm<TestType>>(
     372           4 :             weight, L2NormPow2<TestType>{LinearResidual{bReg}}));
     373           4 :         regTerms.push_back(std::make_unique<RegularizationTerm<TestType>>(
     374           4 :             weight, L2NormPow2<TestType>{LinearResidual{AReg}}));
     375           4 :         regTerms.push_back(std::make_unique<RegularizationTerm<TestType>>(
     376           4 :             weight, L2NormPow2<TestType>{LinearResidual{AReg, bReg}}));
     377           4 :         regTerms.push_back(std::make_unique<RegularizationTerm<TestType>>(
     378           4 :             weight, WeightedL2NormPow2{LinearResidual{AReg, bReg}, isoWReg}));
     379           4 :         regTerms.push_back(std::make_unique<RegularizationTerm<TestType>>(
     380           4 :             weight, WeightedL2NormPow2{LinearResidual{AReg, bReg}, nonIsoWReg}));
     381             : 
     382           4 :         std::array descriptions = {"has no operator and no vector",
     383           4 :                                    "has no operator, but has a vector",
     384           4 :                                    "has an operator, but no vector",
     385           4 :                                    "has an operator and a vector",
     386           4 :                                    "has an operator and a vector, and is weighted (isotropic)",
     387           4 :                                    "has an operator and a vector, and is weighted (nonisotropic)"};
     388             : 
     389          28 :         for (std::size_t i = 0; i < descriptions.size(); i++) {
     390         168 :             for (std::size_t j = 0; j < descriptions.size(); j++) {
     391         144 :                 WHEN("Trying different settings")
     392         144 :                 {
     393           2 :                     INFO("The data term ", descriptions[i]);
     394           2 :                     INFO("The regularization term ", descriptions[j]);
     395           2 :                     Eigen::Matrix<TestType, Eigen::Dynamic, 1> xVec =
     396           2 :                         Eigen::Matrix<TestType, Eigen::Dynamic, 1>::Random(343);
     397           2 :                     DataContainer<TestType> x{desc, xVec};
     398           2 :                     Problem prob{*dataTerms[i], *regTerms[j], x};
     399             : 
     400           2 :                     THEN("the problem can be converted and all operations yield the same result as "
     401           2 :                          "for the initial problem")
     402           2 :                     {
     403           2 :                         WLSProblem<TestType> converted{prob};
     404           2 :                         REQUIRE_UNARY(checkApproxEq(prob.evaluate(), converted.evaluate()));
     405             : 
     406           2 :                         auto gradDiff = prob.getGradient();
     407           2 :                         gradDiff -= converted.getGradient();
     408           2 :                         REQUIRE_UNARY(checkApproxEq(gradDiff.squaredL2Norm(), 0));
     409           2 :                     }
     410           2 :                 }
     411         144 :             }
     412          24 :         }
     413           4 :     }
     414             : 
     415          18 :     GIVEN("a TikhonovProblem with L2 regularization")
     416          18 :     {
     417           2 :         VolumeDescriptor desc{IndexVector_t::Constant(1, 343)};
     418           2 :         Eigen::Matrix<TestType, Eigen::Dynamic, 1> vec =
     419           2 :             Eigen::Matrix<TestType, Eigen::Dynamic, 1>::Random(343);
     420           2 :         DataContainer<TestType> b{desc, vec};
     421             : 
     422           2 :         Scaling<TestType> A{desc, static_cast<TestType>(2.0)};
     423           2 :         WLSProblem<TestType> prob{A, b};
     424             : 
     425           2 :         TestType regWeight = 4.0;
     426           2 :         TikhonovProblem<TestType> l2Reg{prob,
     427           2 :                                         RegularizationTerm{regWeight, L2NormPow2<TestType>{desc}}};
     428             : 
     429           2 :         THEN("the problem can be converted into a block form WLSProblem")
     430           2 :         {
     431           2 :             WLSProblem<TestType> conv{l2Reg};
     432             : 
     433           2 :             Scaling<TestType> lambdaScaling(desc, std::sqrt(regWeight));
     434           2 :             std::vector<std::unique_ptr<LinearOperator<TestType>>> opList(0);
     435           2 :             opList.push_back(A.clone());
     436           2 :             opList.push_back(lambdaScaling.clone());
     437           2 :             BlockLinearOperator<TestType> blockOp{opList,
     438           2 :                                                   BlockLinearOperator<TestType>::BlockType::ROW};
     439             : 
     440           2 :             std::vector<std::unique_ptr<DataDescriptor>> descList(0);
     441           2 :             descList.push_back(desc.clone());
     442           2 :             descList.push_back(desc.clone());
     443           2 :             RandomBlocksDescriptor vecDesc{descList};
     444           2 :             DataContainer<TestType> blockVec{vecDesc};
     445           2 :             blockVec.getBlock(0) = b;
     446           2 :             blockVec.getBlock(1) = 0;
     447             : 
     448           2 :             L2NormPow2<TestType> blockWls{LinearResidual<TestType>{blockOp, blockVec}};
     449           2 :             REQUIRE_EQ(conv.getDataTerm(), blockWls);
     450           2 :             REQUIRE_UNARY(conv.getRegularizationTerms().empty());
     451           2 :         }
     452           2 :     }
     453          18 : }
     454             : 
     455             : TEST_SUITE_END();

Generated by: LCOV version 1.14