Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
lfit_test.cc
Go to the documentation of this file.
1#include <gtest/gtest.h>
2#include <lfit.H>
3#include <cmath>
4
5class LFitTest : public ::testing::Test
6{
7protected:
8 void SetUp() override {}
9 void TearDown() override {}
10
11 bool approx_equal(double a, double b, double eps = 1e-6) {
12 return std::abs(a - b) < eps;
13 }
14};
15
16// =============================================================================
17// Basic Fitting Tests
18// =============================================================================
19
21{
22 // y = 2x + 1
23 Array<double> x = {1, 2, 3, 4, 5};
24 Array<double> y = {3, 5, 7, 9, 11};
25
26 LFit fit(x, y);
27
28 EXPECT_TRUE(approx_equal(fit.m, 2.0, 1e-10));
29 EXPECT_TRUE(approx_equal(fit.c, 1.0, 1e-10));
30 EXPECT_TRUE(approx_equal(fit.r2, 1.0, 1e-10));
31 EXPECT_TRUE(approx_equal(fit.sumsq, 0.0, 1e-10));
32}
33
35{
36 Array<double> x = {1, 2, 3, 4, 5};
37 Array<double> y = {5, 5, 5, 5, 5};
38
39 LFit fit(x, y);
40
41 EXPECT_TRUE(approx_equal(fit.m, 0.0, 1e-10));
42 EXPECT_TRUE(approx_equal(fit.c, 5.0, 1e-10));
43}
44
46{
47 // y = x (45 degree line)
48 Array<double> x = {0, 1, 2, 3, 4};
49 Array<double> y = {0, 1, 2, 3, 4};
50
51 LFit fit(x, y);
52
53 EXPECT_TRUE(approx_equal(fit.m, 1.0, 1e-10));
54 EXPECT_TRUE(approx_equal(fit.c, 0.0, 1e-10));
55 EXPECT_TRUE(approx_equal(fit.r2, 1.0, 1e-10));
56}
57
59{
60 // y = -2x + 10
61 Array<double> x = {1, 2, 3, 4, 5};
62 Array<double> y = {8, 6, 4, 2, 0};
63
64 LFit fit(x, y);
65
66 EXPECT_TRUE(approx_equal(fit.m, -2.0, 1e-10));
67 EXPECT_TRUE(approx_equal(fit.c, 10.0, 1e-10));
68 EXPECT_TRUE(approx_equal(fit.r2, 1.0, 1e-10));
69}
70
71// =============================================================================
72// Noisy Data Tests
73// =============================================================================
74
76{
77 // y = 2x + 1 with small noise
78 Array<double> x = {1, 2, 3, 4, 5};
79 Array<double> y = {3.1, 4.9, 7.1, 8.9, 11.0};
80
81 LFit fit(x, y);
82
83 EXPECT_TRUE(approx_equal(fit.m, 2.0, 0.2));
84 EXPECT_TRUE(approx_equal(fit.c, 1.0, 0.2));
85 EXPECT_GT(fit.r2, 0.95);
86}
87
89{
90 Array<double> x = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
91 Array<double> y = {2.5, 4.2, 6.1, 7.8, 10.3, 12.1, 13.9, 16.2, 17.8, 20.1};
92
93 LFit fit(x, y);
94
95 EXPECT_GT(fit.m, 1.5);
96 EXPECT_LT(fit.m, 2.5);
97 EXPECT_GT(fit.r2, 0.9);
98}
99
100// =============================================================================
101// Prediction Tests
102// =============================================================================
103
105{
106 Array<double> x = {1, 2, 3, 4, 5};
107 Array<double> y = {3, 5, 7, 9, 11};
108
109 LFit fit(x, y);
110
111 auto [pred, err] = fit.predict(3.0);
112 EXPECT_TRUE(approx_equal(pred, 7.0, 1e-10));
113}
114
116{
117 Array<double> x = {1, 2, 3, 4, 5};
118 Array<double> y = {3, 5, 7, 9, 11};
119
120 LFit fit(x, y);
121
122 auto [pred, err] = fit.predict(10.0);
123 EXPECT_TRUE(approx_equal(pred, 21.0, 1e-10));
124}
125
127{
128 Array<double> x = {0, 1, 2, 3, 4};
129 Array<double> y = {1, 3, 5, 7, 9};
130
131 LFit fit(x, y);
132
133 for (double xval = 0; xval <= 4; xval += 0.5)
134 {
135 auto [pred, err] = fit.predict(xval);
136 double expected = 2.0 * xval + 1.0;
138 }
139}
140
141// =============================================================================
142// Edge Cases Tests
143// =============================================================================
144
146{
147 Array<double> x = {1, 5};
148 Array<double> y = {2, 10};
149
150 LFit fit(x, y);
151
152 EXPECT_TRUE(approx_equal(fit.m, 2.0, 1e-10));
153 EXPECT_TRUE(approx_equal(fit.r2, 1.0, 1e-10));
154}
155
157{
158 Array<double> x = {1000, 2000, 3000, 4000, 5000};
159 Array<double> y = {2000, 4000, 6000, 8000, 10000};
160
161 LFit fit(x, y);
162
163 EXPECT_TRUE(approx_equal(fit.m, 2.0, 1e-6));
164}
165
167{
168 Array<double> x = {0.001, 0.002, 0.003, 0.004, 0.005};
169 Array<double> y = {0.002, 0.004, 0.006, 0.008, 0.010};
170
171 LFit fit(x, y);
172
173 EXPECT_TRUE(approx_equal(fit.m, 2.0, 1e-6));
174}
175
177{
178 Array<double> x = {-5, -4, -3, -2, -1};
179 Array<double> y = {-10, -8, -6, -4, -2};
180
181 LFit fit(x, y);
182
183 EXPECT_TRUE(approx_equal(fit.m, 2.0, 1e-10));
184}
185
186// =============================================================================
187// Statistical Properties Tests
188// =============================================================================
189
191{
192 Array<double> x = {1, 2, 3, 4, 5};
193 Array<double> y = {2.1, 3.9, 6.1, 8.0, 10.2};
194
195 LFit fit(x, y);
196
197 EXPECT_GE(fit.r2, 0.0);
198 EXPECT_LE(fit.r2, 1.0);
199}
200
202{
203 Array<double> x = {1, 2, 3, 4, 5};
204 Array<double> y = {3, 5, 7, 9, 11};
205
206 LFit fit(x, y);
207
208 EXPECT_GE(fit.sumsq, 0.0);
209 EXPECT_TRUE(approx_equal(fit.sumsq, 0.0, 1e-10));
210}
211
213{
214 Array<double> x = {1, 2, 3, 4, 5};
215 Array<double> y = {3.1, 5.2, 6.9, 9.1, 10.8};
216
217 LFit fit(x, y);
218
219 EXPECT_GE(fit.mse, 0.0);
220 EXPECT_GT(fit.sigma, 0.0);
221}
222
223// =============================================================================
224// Different Data Patterns Tests
225// =============================================================================
226
228{
229 Array<double> x = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
231
232 for (size_t i = 0; i < x.size(); ++i)
233 y.append(3.0 * x[i] + 2.0);
234
235 LFit fit(x, y);
236
237 EXPECT_TRUE(approx_equal(fit.m, 3.0, 1e-10));
238 EXPECT_TRUE(approx_equal(fit.c, 2.0, 1e-10));
239}
240
242{
243 Array<double> x = {1, 3, 5, 10, 15};
244 Array<double> y = {2, 6, 10, 20, 30};
245
246 LFit fit(x, y);
247
248 EXPECT_TRUE(approx_equal(fit.m, 2.0, 1e-10));
249}
250
252{
253 Array<double> x = {5, 4, 3, 2, 1};
254 Array<double> y = {11, 9, 7, 5, 3};
255
256 LFit fit(x, y);
257
258 EXPECT_TRUE(approx_equal(fit.m, 2.0, 1e-10));
259 EXPECT_TRUE(approx_equal(fit.c, 1.0, 1e-10));
260}
261
262// =============================================================================
263// Stress Tests
264// =============================================================================
265
267{
268 Array<double> x, y;
269
270 for (int i = 0; i < 1000; ++i)
271 {
272 x.append(i);
273 y.append(2.5 * i + 10.0);
274 }
275
276 LFit fit(x, y);
277
278 EXPECT_TRUE(approx_equal(fit.m, 2.5, 1e-10));
279 EXPECT_TRUE(approx_equal(fit.c, 10.0, 1e-8));
280 EXPECT_TRUE(approx_equal(fit.r2, 1.0, 1e-10));
281}
282
284{
285 Array<double> x = {1, 2, 3, 4, 5};
286 Array<double> y = {2, 4, 6, 8, 10};
287
288 LFit fit(x, y);
289
290 for (int i = -10; i <= 20; ++i)
291 {
292 auto [pred, err] = fit.predict(i);
293 EXPECT_TRUE(approx_equal(pred, 2.0 * i, 1e-10));
294 }
295}
296
298{
299 Array<double> x = {1, 2, 3, 4, 5};
300 Array<double> y = {3, 5, 7, 9, 11};
301
302 for (int i = 0; i < 100; ++i)
303 {
304 LFit fit(x, y);
305 EXPECT_TRUE(approx_equal(fit.m, 2.0, 1e-10));
306 EXPECT_TRUE(approx_equal(fit.c, 1.0, 1e-10));
307 }
308}
309
310// =============================================================================
311// Comparison Tests
312// =============================================================================
313
315{
316 Array<double> x = {1, 2, 3, 4, 5};
317
318 Array<double> y1 = {2, 4, 6, 8, 10};
319 LFit fit1(x, y1);
320
321 Array<double> y2 = {3, 6, 9, 12, 15};
322 LFit fit2(x, y2);
323
324 EXPECT_TRUE(approx_equal(fit1.m, 2.0, 1e-10));
325 EXPECT_TRUE(approx_equal(fit2.m, 3.0, 1e-10));
326 EXPECT_GT(fit2.m, fit1.m);
327}
328
330{
331 Array<double> x = {1, 2, 3, 4, 5};
332
333 Array<double> y1 = {3, 5, 7, 9, 11};
334 LFit fit1(x, y1);
335
336 Array<double> y2 = {5, 7, 9, 11, 13};
337 LFit fit2(x, y2);
338
339 EXPECT_TRUE(approx_equal(fit1.c, 1.0, 1e-10));
340 EXPECT_TRUE(approx_equal(fit2.c, 3.0, 1e-10));
341 EXPECT_GT(fit2.c, fit1.c);
342}
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:138
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:333
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:239
void TearDown() override
Definition lfit_test.cc:9
void SetUp() override
Definition lfit_test.cc:8
bool approx_equal(double a, double b, double eps=1e-6)
Definition lfit_test.cc:11
bool approx_equal(double a, double b, double tol=EPSILON)
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_y1_function > > y1(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4103
Freq_Node * pred
Predecessor node in level-order traversal.
Linear regression (least squares fitting) using GSL.
TEST_F(LFitTest, PerfectLineFit)
Definition lfit_test.cc:20
static mpfr_t y
Definition mpfr_mul_d.c:3
DynList< T > maps(const C &c, Op op)
Classic map operation.
Linear regression calculator using least squares method.
Definition lfit.H:99