SOPT
Sparse OPTimisation
Functions
maths.cc File Reference
#include <catch2/catch_all.hpp>
#include <numeric>
#include <random>
#include <utility>
#include "sopt/maths.h"
#include "sopt/relative_variation.h"
#include "sopt/sampling.h"
#include "sopt/types.h"
+ Include dependency graph for maths.cc:

Go to the source code of this file.

Functions

 TEST_CASE ("Projector on positive quadrant", "[utility][project]")
 
 TEST_CASE ("Weighted l1 norm", "[utility][l1]")
 
 TEST_CASE ("Soft threshhold", "[utility][threshhold]")
 
 TEST_CASE ("Sampling", "[utility][sampling]")
 
 TEST_CASE ("Relative variation", "[utility][convergence]")
 
 TEST_CASE ("Scalar elative variation", "[utility][convergence]")
 
 TEST_CASE ("Standard deviation", "[utility]")
 

Function Documentation

◆ TEST_CASE() [1/7]

TEST_CASE ( "Projector on positive quadrant"  ,
""  [utility][project] 
)

Definition at line 13 of file maths.cc.

13  {
14  using namespace sopt;
15 
16  SECTION("Real matrix") {
17  Image<> input = Image<>::Ones(5, 5) + Image<>::Random(5, 5) * 0.55;
18  input(1, 1) *= -1;
19  input(3, 2) *= -1;
20 
21  auto const expr = positive_quadrant(input);
22  CAPTURE(input);
23  CAPTURE(expr);
24  CHECK(expr(1, 1) == Approx(0));
25  CHECK(expr(3, 2) == Approx(0));
26 
27  auto value = expr.eval();
28  CHECK(value(1, 1) == Approx(0));
29  CHECK(value(3, 2) == Approx(0));
30  value(1, 1) = input(1, 1);
31  value(3, 2) = input(3, 2);
32  CHECK(value.isApprox(input));
33  }
34 
35  SECTION("Complex matrix") {
37  input.real()(1, 1) *= -1;
38  input.real()(3, 2) *= -1;
39 
40  auto const expr = positive_quadrant(input);
41  CAPTURE(input);
42  CAPTURE(expr);
43  CHECK(expr.imag().isApprox(Image<>::Zero(5, 5)));
44 
45  auto value = expr.eval();
46  CHECK(value.real()(1, 1) == Approx(0));
47  CHECK(value.real()(3, 2) == Approx(0));
48  value(1, 1) = input.real()(1, 1);
49  value(3, 2) = input.real()(3, 2);
50  CHECK(value.real().isApprox(input.real()));
51  CHECK(value.imag().isApprox(0e0 * input.real()));
52  }
53 }
Eigen::CwiseUnaryOp< const details::ProjectPositiveQuadrant< typename T::Scalar >, const T > positive_quadrant(Eigen::DenseBase< T > const &input)
Expression to create projection onto positive quadrant.
Definition: maths.h:60
Eigen::Array< T, Eigen::Dynamic, Eigen::Dynamic > Image
A 2-dimensional list of elements of given type.
Definition: types.h:39

References sopt::positive_quadrant().

◆ TEST_CASE() [2/7]

TEST_CASE ( "Relative variation"  ,
""  [utility][convergence] 
)

Definition at line 148 of file maths.cc.

148  {
149  sopt::RelativeVariation<double> relvar(1e-8);
150 
151  sopt::Array<> const input = sopt::Array<>::Random(6);
152  CHECK(not relvar(input));
153  CHECK(relvar(input));
154  CHECK(relvar(input + relvar.tolerance() * 0.5 / 6. * sopt::Array<>::Random(6)));
155  CHECK(not relvar(input + relvar.tolerance() * 1.1 * sopt::Array<>::Ones(6)));
156 }
Eigen::Array< T, Eigen::Dynamic, 1 > Array
A 1-dimensional list of elements of given type.
Definition: types.h:34

References sopt::RelativeVariation< TYPE >::tolerance().

◆ TEST_CASE() [3/7]

TEST_CASE ( "Sampling"  ,
""  [utility][sampling] 
)

Definition at line 121 of file maths.cc.

121  {
122  using t_Vector = sopt::Vector<int>;
123  t_Vector const input = t_Vector::Random(12);
124 
125  sopt::Sampling const sampling(12, {1, 3, 6, 5});
126 
127  t_Vector down = t_Vector::Zero(4);
128  sampling(down, input);
129  CHECK(down.size() == 4);
130  CHECK(down(0) == input(1));
131  CHECK(down(1) == input(3));
132  CHECK(down(2) == input(6));
133  CHECK(down(3) == input(5));
134 
135  t_Vector up = t_Vector::Zero(input.size());
136  sampling.adjoint(up, down);
137  CHECK(up(1) == input(1));
138  CHECK(up(3) == input(3));
139  CHECK(up(6) == input(6));
140  CHECK(up(5) == input(5));
141  up(1) = 0;
142  up(3) = 0;
143  up(6) = 0;
144  up(5) = 0;
145  CHECK(up == t_Vector::Zero(up.size()));
146 }
sopt::Vector< Scalar > t_Vector
An operator that samples a set of measurements.
Definition: sampling.h:17
Eigen::Matrix< T, Eigen::Dynamic, 1 > Vector
A vector of a given type.
Definition: types.h:24

◆ TEST_CASE() [4/7]

TEST_CASE ( "Scalar elative variation"  ,
""  [utility][convergence] 
)

Definition at line 158 of file maths.cc.

158  {
159  sopt::ScalarRelativeVariation<double> relvar(1e-8, 1e-8, "Yo");
160  sopt::t_real const input = sopt::Array<>::Random(1)(0);
161  CHECK(not relvar(input));
162  CHECK(relvar(input));
163  CHECK(not relvar(input + 0.1));
164  CHECK(relvar(input + 0.1 + 0.1 * relvar.relative_tolerance()));
165 }
double t_real
Root of the type hierarchy for real numbers.
Definition: types.h:17

References sopt::ScalarRelativeVariation< TYPE >::relative_tolerance().

◆ TEST_CASE() [5/7]

TEST_CASE ( "Soft threshhold"  ,
""  [utility][threshhold] 
)

Definition at line 72 of file maths.cc.

72  {
73  sopt::Array<> input(6);
74  input << 1e1, 2e1, 3e1, 4e1, 1e4, 2e4;
75 
76  SECTION("Single-valued threshhold") {
77  // check thresshold
78  CHECK(sopt::soft_threshhold(input, 1.1e1)(0) == Approx(0));
79  CHECK(not(sopt::soft_threshhold(input, 1.1e1)(1) == Approx(0)));
80 
81  // check linearity
82  auto a = sopt::soft_threshhold(input, 9e0)(0);
83  auto b = sopt::soft_threshhold(input, 4.5e0)(0);
84  auto c = sopt::soft_threshhold(input, 2.25e0)(0);
85  CAPTURE(b - a);
86  CAPTURE(c - b);
87  CHECK((b - a) == Approx(2 * (c - b)));
88  }
89 
90  SECTION("Multi-values threshhold") {
91  using namespace sopt;
92  Array<> threshhold(6);
93  input[2] *= -1;
94  threshhold << 1.1e1, 1.1e1, 1e0, 4.5, 2.25, 2.26;
95 
96  SECTION("Real input") {
97  Array<> const actual = soft_threshhold(input, threshhold);
98  CHECK(actual(0) == 0e0);
99  CHECK(actual(1) == input(1) - threshhold(1));
100  CHECK(actual(2) == input(2) + threshhold(2));
101  CHECK(actual(3) == input(3) - threshhold(3));
102 
103 #ifdef CATCH_HAS_THROWS_AS
104  CHECK_THROWS_AS(soft_threshhold(input, threshhold.head(2)), sopt::Exception);
105 #endif
106  }
107  SECTION("Complex input") {
108  Array<t_complex> const actual = soft_threshhold(input.cast<t_complex>(), threshhold);
109  CHECK(actual(0) == 0e0);
110  CHECK(actual(1) == input(1) - threshhold(1));
111  CHECK(actual(2) == input(2) + threshhold(2));
112  CHECK(actual(3) == input(3) - threshhold(3));
113 
114 #ifdef CATCH_HAS_THROWS_AS
115  CHECK_THROWS_AS(soft_threshhold(input, threshhold.head(2)), sopt::Exception);
116 #endif
117  }
118  }
119 }
constexpr Scalar b
constexpr Scalar a
Root exception for sopt.
Definition: exception.h:11
std::enable_if< std::is_arithmetic< SCALAR >::value or is_complex< SCALAR >::value, SCALAR >::type soft_threshhold(SCALAR const &x, typename real_type< SCALAR >::type const &threshhold)
abs(x) < threshhold ? 0: x - sgn(x) * threshhold
Definition: maths.h:29
std::complex< t_real > t_complex
Root of the type hierarchy for (real) complex numbers.
Definition: types.h:19

References a, b, and sopt::soft_threshhold().

◆ TEST_CASE() [6/7]

TEST_CASE ( "Standard deviation"  ,
""  [utility] 
)

Definition at line 167 of file maths.cc.

167  {
169  sopt::t_complex const mean = input.mean();
170  sopt::t_real stddev = 0e0;
171  for (sopt::Vector<>::Index i(0); i < input.size(); ++i)
172  stddev += std::real(std::conj(input(i) - mean) * (input(i) - mean));
173  stddev = std::sqrt(stddev) / std::sqrt(static_cast<sopt::t_real>(input.size()));
174 
175  CHECK(std::abs(sopt::standard_deviation(input) - stddev) < 1e-8);
176  CHECK(std::abs(sopt::standard_deviation(input.matrix()) - stddev) < 1e-8);
177 }
real_type< typename T::Scalar >::type standard_deviation(Eigen::ArrayBase< T > const &x)
Computes the standard deviation of a vector.
Definition: maths.h:16

References sopt::standard_deviation().

◆ TEST_CASE() [7/7]

TEST_CASE ( "Weighted l1 norm"  ,
""  [utility][l1] 
)

Definition at line 55 of file maths.cc.

55  {
56  sopt::Array<> weight(4);
57  weight << 1, 2, 3, 4;
58 
59  SECTION("Real valued") {
60  sopt::Array<> input(4);
61  input << 5, -6, 7, -8;
62  CHECK(sopt::l1_norm(input, weight) == Approx(5 + 12 + 21 + 32));
63  }
64  SECTION("Complex valued") {
65  sopt::t_complex const i(0, 1);
67  input << 5. + 5. * i, 6. + 6. * i, 7. + 7. * i, 8. + 8. * i;
68  CHECK(sopt::l1_norm(input, weight) == Approx(std::sqrt(2) * (5 + 12 + 21 + 32)));
69  }
70 }
real_type< typename T0::Scalar >::type l1_norm(Eigen::ArrayBase< T0 > const &input, Eigen::ArrayBase< T1 > const &weights)
Computes weighted L1 norm.
Definition: maths.h:116

References sopt::l1_norm().