Lumiera  0.pre.03
»edit your freedom«
statistic-test.cpp
Go to the documentation of this file.
1 /*
2  Statistic(Test) - validate simple statistic calculations
3 
4  Copyright (C)
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
19 #include "lib/test/run.hpp"
20 #include "lib/test/test-helper.hpp"
21 #include "lib/stat/statistic.hpp"
22 #include "lib/iter-explorer.hpp"
23 #include "lib/format-util.hpp"
24 #include "lib/random.hpp"
25 #include "lib/util.hpp"
26 #include "lib/format-cout.hpp"
28 
29 
30 
31 namespace lib {
32 namespace stat{
33 namespace test{
34 
35  namespace {
36  const size_t NUM_POINTS = 1'000;
37  }
38 
39  using lib::test::roughEQ;
40  using util::isnil;
41  using error::LUMIERA_ERROR_INVALID;
42 
43 
44  /**************************************************************//**
45  * @test verifies the proper working of statistic helper functions.
46  * - calculate mean and standard derivation
47  * - one-dimensional linear regression
48  * @see DataCSV_test.hpp
49  * @see statistic.hpp
50  */
51  class Statistic_test : public Test
52  {
53  void
54  run (Arg)
55  {
56  demonstrate_DataSpan();
57  check_baseStatistics();
58  check_wightedLinearRegression();
59  check_TimeSeriesLinearRegression();
60  }
61 
62 
63 
65  void
66  demonstrate_DataSpan()
67  {
68  auto dat = VecD{0,1,2,3,4,5};
69 
70  DataSpan all{dat};
71  CHECK (not isnil (all));
72  CHECK (dat.size() == all.size());
73 
74  auto i = all.begin();
75  CHECK (i != all.end());
76  CHECK (0 == *i);
77  ++i;
78  CHECK (1 == *i);
79 
80  DataSpan innr{*i, dat.back()};
81  CHECK (util::join(innr) == "1, 2, 3, 4"_expect);
82  CHECK (2 == innr.at(1));
83  CHECK (2 == innr[1]);
84  CHECK (4 == innr[3]);
85  CHECK (5 == innr[4]); // »undefined behaviour«
86 
87  VERIFY_ERROR (INVALID, innr.at(4) )
88 
89  CHECK (1+2+3+4 == lib::explore(innr).resultSum());
90  }
91 
92 
94  void
95  check_baseStatistics ()
96  {
97  auto dat = VecD{4,2,5,8,6};
98  DataSpan all = lastN(dat, dat.size());
99  DataSpan rst = lastN(dat, 4);
100  CHECK (2 == *rst.begin());
101  CHECK (4 == rst.size());
102  CHECK (5 == all.size());
103 
104  CHECK (5.0 == average (all));
105  CHECK (5.25 == average(rst));
106 
107  // Surprise : divide by N-1 since it is a guess for the real standard derivation
108  CHECK (sdev (all, 5.0) == sqrt(20/(5-1)));
109 
110  CHECK (5.0 == averageLastN (dat,20));
111  CHECK (5.0 == averageLastN (dat, 5));
112  CHECK (5.25 == averageLastN (dat, 4));
113  CHECK (7.0 == averageLastN (dat, 2));
114  CHECK (6.0 == averageLastN (dat, 1));
115  CHECK (0.0 == averageLastN (dat, 0));
116  }
117 
118 
127  void
128  check_wightedLinearRegression()
129  {
130  RegressionData points{{1,1, 1}
131  ,{5,5, 1}
132  ,{3,1, 2}
133  };
134 
135  auto [socket,gradient
136  ,predicted,deltas
137  ,correlation
138  ,maxDelta
139  ,sdev] = computeLinearRegression (points);
140 
141  CHECK (socket == -1);
142  CHECK (gradient == 1);
143  CHECK (util::join (predicted) == "0, 4, 2"_expect );
144  CHECK (util::join (deltas) == "1, 1, -1"_expect );
145  CHECK (maxDelta == 1);
146  CHECK (correlation == "0.81649658"_expect );
147  CHECK (sdev == "1.7320508"_expect );
148  }
149 
150 
151 
156  void
157  check_TimeSeriesLinearRegression()
158  {
159  auto dirt = [] { return ranRange(-0.5,+0.5); };
160  auto fun = [&](uint i){ auto x = double(i)/NUM_POINTS;
161  return x*x;
162  };
163  VecD data;
164  data.reserve (NUM_POINTS);
165  for (uint i=0; i<NUM_POINTS; ++i)
166  data.push_back (fun(i) + dirt());
167 
168  auto [socket,gradient,correlation] = computeTimeSeriesLinearRegression (data);
169 
170  // regression line should roughly connect 0 to 1,
171  // yet slightly shifted downwards, cutting through the parabolic curve
172  CHECK (roughEQ (gradient*NUM_POINTS, 1, 0.08));
173  CHECK (roughEQ (socket, -0.16, 0.3 ));
174  CHECK (correlation > 0.65);
175  }
176  };
177 
178  LAUNCHER (Statistic_test, "unit calculation");
179 
180 
181 }}} // namespace lib::stat::test
182 
Automatically use custom string conversion in C++ stream output.
Definition: run.hpp:40
Helpers typically used while writing tests.
Implementation namespace for support and library code.
Simplistic test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
A collection of frequently used helper functions to support unit testing.
Generating (pseudo) random numbers with controlled seed.
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
Building tree expanding and backtracking evaluations within hierarchical scopes.