ROOT
ROOT project
Loading...
Searching...
No Matches
solver_tester.hpp
Go to the documentation of this file.
1#ifndef SOLVER_TESTER_HPP
2#define SOLVER_TESTER_HPP
3
4#include <gtest/gtest.h>
5
6#include <Eigen/Dense>
7#include <libROOT/solver.hpp>
8#include <libROOT/stepper.hpp>
9
10class SolverTester : public ::testing::Test {
11 public:
12 template <typename T>
13 void testConverStepper(std::function<double(double)> func, T initial_guess, Method method,
14 std::function<double(double)> derivative_or_function_g = nullptr) {
15 Solver<T> solver(func, initial_guess, method, 100, 1e-6, false, false, derivative_or_function_g);
16 std::unique_ptr<StepperBase<T>> stepper;
17 solver.convert_stepper(stepper);
18 ASSERT_NE(stepper, nullptr) << "Stepper conversion failed for method.";
19
20 // checks to verify the type of the stepper
21 switch (method) {
22 case Method::NEWTON:
23 if constexpr (std::is_same<T, double>::value) {
24 ASSERT_NE(dynamic_cast<NewtonRaphsonStepper<double>*>(stepper.get()), nullptr)
25 << "Stepper is not of type NewtonRaphsonStepper for scalar initial guess.";
26 } else if constexpr (std::is_same<T, Eigen::Vector2d>::value) {
27 ASSERT_NE(dynamic_cast<NewtonRaphsonStepper<Eigen::Vector2d>*>(stepper.get()), nullptr)
28 << "Stepper is not of type NewtonRaphsonStepper for vector initial guess.";
29 }
30 break;
32 if constexpr (std::is_same<T, double>::value) {
33 ASSERT_NE(dynamic_cast<FixedPointStepper<double>*>(stepper.get()), nullptr)
34 << "Stepper is not of type FixedPointStepper for scalar initial guess.";
35 } else if constexpr (std::is_same<T, Eigen::Vector2d>::value) {
36 ASSERT_NE(dynamic_cast<FixedPointStepper<Eigen::Vector2d>*>(stepper.get()), nullptr)
37 << "Stepper is not of type FixedPointStepper for vector initial guess.";
38 }
39 break;
41 if constexpr (std::is_same<T, double>::value) {
42 ASSERT_NE(dynamic_cast<BisectionStepper<double>*>(stepper.get()), nullptr)
43 << "Stepper is not of type BisectionStepper for scalar initial guess.";
44 }
45 break;
46 case Method::CHORDS:
47 if constexpr (std::is_same<T, double>::value) {
48 ASSERT_NE(dynamic_cast<ChordsStepper<double>*>(stepper.get()), nullptr)
49 << "Stepper is not of type ChordsStepper for scalar initial guess.";
50 }
51 break;
52 default:
53 FAIL() << "Unknown method provided.";
54 }
55 }
56
58 auto func = [](double x) { return x * x - 2; };
59 double initial_guess = 1.0;
60 Solver<double> solver(func, initial_guess, Method::NEWTON, 100, 1e-6, false, false,
61 [](double x) { return 2 * x; });
62
63 Eigen::Vector2d result_to_save;
64 result_to_save << 1.41421, 0.0;
65 solver.save_results(0, result_to_save);
66
67 Eigen::Vector2d retrieved_result = solver.get_previous_result(0);
68 ASSERT_DOUBLE_EQ(retrieved_result(0), result_to_save(0)) << "Saved and retrieved x values do not match.";
69 ASSERT_DOUBLE_EQ(retrieved_result(1), result_to_save(1)) << "Saved and retrieved f(x) values do not match.";
70 }
71
73 auto func = [](double x) { return x * x - 2; };
74 double initial_guess = 1.0;
75 Solver<double> solver(func, initial_guess, Method::NEWTON, 100, 1e-6, false, false,
76 [](double x) { return 2 * x; });
77
78 double x_prev = 1.0;
79 double x_next = 1.41421;
80 double expected_error = std::abs(x_next - x_prev);
81 double calculated_error = solver.calculate_error(x_prev, x_next);
82
83 ASSERT_DOUBLE_EQ(calculated_error, expected_error) << "Calculated error does not match expected error.";
84 }
85
87 auto func = [](double x) { return x * x - 2; };
88 double initial_guess = 1.0;
89 Solver<double> solver(func, initial_guess, Method::NEWTON, 100, 1e-6, false, false,
90 [](double x) { return 2 * x; });
91
92 solver.save_starting_point();
93
94 Eigen::Vector2d retrieved_result = solver.get_previous_result(solver.results.rows() - 1);
95 ASSERT_DOUBLE_EQ(retrieved_result(0), initial_guess) << "Saved starting point x does not match initial guess.";
96 ASSERT_DOUBLE_EQ(retrieved_result(1), func(initial_guess))
97 << "Saved starting point f(x) does not match function evaluation at initial guess.";
98 }
99
101 auto func = [](double x) { return x * x - 2; };
102 double initial_guess = 1.0;
103 Solver<double> solver(func, initial_guess, Method::NEWTON, 100, 1e-6, false, false,
104 [](double x) { return 2 * x; });
105
106 Eigen::Vector2d first_result;
107 first_result << 1.41421, 0.0;
108 solver.save_results(0, first_result);
109
110 Eigen::Vector2d second_result;
111 second_result << 1.73205, 0.0;
112 solver.save_results(1, second_result);
113
114 Eigen::Vector2d retrieved_first_result = solver.get_previous_result(1);
115 ASSERT_DOUBLE_EQ(retrieved_first_result(0), first_result(0)) << "Retrieved previous x value does not match.";
116 ASSERT_DOUBLE_EQ(retrieved_first_result(1), first_result(1)) << "Retrieved previous f(x) value does not match.";
117 }
118
119 template <typename T>
120 void testSolverStep(std::function<double(double)> func, T initial_guess, Method method,
121 std::function<double(double)> derivative_or_function_g = nullptr) {
122 Solver<T> solver(func, initial_guess, method, 100, 1e-6, false, false, derivative_or_function_g);
123 std::unique_ptr<StepperBase<T>> stepper;
124 solver.convert_stepper(stepper);
125 ASSERT_NE(stepper, nullptr) << "Stepper conversion failed for method.";
126
127 double err = 1;
128 int iter = 1;
129
130 solver.save_starting_point();
131 solver.solver_step(iter, stepper, err);
132
133 ASSERT_NE(err, 1) << "Error was not updated in solver_step.";
134 ASSERT_EQ(iter, 2) << "Iteration count was not incremented in solver_step.";
135 ASSERT_EQ(solver.results.rows(), 2) << "Results were not saved in solver_step.";
136 }
137
138 template <typename T>
139 void testSolve(std::function<double(double)> func, T initial_guess, Method method,
140 std::function<double(double)> derivative_or_function_g = nullptr, int max_iterations = 100) {
141 Solver<T> solver(func, initial_guess, method, max_iterations, 1e-6, false, false, derivative_or_function_g);
142 solver.solve();
143
144 ASSERT_GT(solver.results.rows(), 0) << "No results were recorded during solve.";
145 double final_x = solver.results(solver.results.rows() - 1, 0);
146 double final_fx = solver.results(solver.results.rows() - 1, 1);
147 ASSERT_NEAR(final_fx, 0.0, 1e-4) << "Final function value is not close to zero.";
148 }
149};
150
151#endif // SOLVER_TESTER_HPP
The specialized Stepper to compute a step with the Bisection Method.
Definition stepper_def.hpp:136
The specialized Stepper to compute a step with the Chords Method (also called Secants in literature)
Definition stepper_def.hpp:110
The specialized Stepper to compute a step with the Fixed Point method.
Definition stepper_def.hpp:87
The specialized Stepper to compute a step with the Newton-Raphson method.
Definition stepper_def.hpp:65
Definition solver_tester.hpp:10
void testGetPreviousResult()
Definition solver_tester.hpp:100
void testSolve(std::function< double(double)> func, T initial_guess, Method method, std::function< double(double)> derivative_or_function_g=nullptr, int max_iterations=100)
Definition solver_tester.hpp:139
void testCalculateError()
Definition solver_tester.hpp:72
void testSolverStep(std::function< double(double)> func, T initial_guess, Method method, std::function< double(double)> derivative_or_function_g=nullptr)
Definition solver_tester.hpp:120
void testSaveStartingPoint()
Definition solver_tester.hpp:86
void testSaveResults()
Definition solver_tester.hpp:57
void testConverStepper(std::function< double(double)> func, T initial_guess, Method method, std::function< double(double)> derivative_or_function_g=nullptr)
Definition solver_tester.hpp:13
Class Solver managing the solving process and creating the Stepper object.
Definition solver_def.hpp:31
void save_results(int iter, Eigen::Vector2d result_to_save)
Saves the result of a step in a defined row of the results' matrix.
Definition solver.hpp:78
Eigen::MatrixX2d solve()
Calls everything required to Solve with a method.
Definition solver.hpp:108
void save_starting_point()
Saves the actual initial guess in the top row of the results' matrix, no matter what type will be the...
void convert_stepper(std::unique_ptr< StepperBase< T > > &stepper)
Converts the generic Abstract stepper into a typed one.
void solver_step(int &iter, std::unique_ptr< StepperBase< T > > &stepper, double &err)
Creates the stepper, calls the step computation, the error calculation and the results' saver.
Definition solver.hpp:149
Eigen::MatrixX2d results
Definition solver_def.hpp:41
Method
Enumeration of available root-finding methods.
Definition method.hpp:8
@ FIXED_POINT
Definition method.hpp:8
@ BISECTION
Definition method.hpp:8
@ CHORDS
Definition method.hpp:8
@ NEWTON
Definition method.hpp:8