ROOT
ROOT project
Loading...
Searching...
No Matches
solver.hpp
Go to the documentation of this file.
1#ifndef ROOT_SOLVER_HPP
2#define ROOT_SOLVER_HPP
3#include <Eigen/Dense>
4#include <iostream>
5#include <memory>
6
7#include "method.hpp"
8#include "solver_def.hpp"
9#include "stepper.hpp"
10
11constexpr double tol = 1e-6;
12constexpr int max_iters = 200;
13
14template <typename T>
15Solver<T>::Solver(std::function<double(double)> fun, T initial_guess, const Method method, int max_iterations,
16 double tolerance, bool aitken_mode, bool verbose) {
17 this->function = fun;
18 this->initial_guess = initial_guess;
19 this->method = method;
20 this->max_iterations = max_iterations;
21 this->tolerance = tolerance;
22 this->results = Eigen::MatrixX2d(0, 2);
23 this->aitken_requirement = aitken_mode;
24 this->verbose = verbose;
25}
26template <typename T>
27Solver<T>::Solver(std::function<double(double)> fun, T initial_guess, const Method method, int max_iterations,
28 double tolerance, bool aitken_mode, bool verbose,
29 std::function<double(double)> derivative_or_function_g) {
30 this->function = fun;
31 this->initial_guess = initial_guess;
32 this->method = method;
33 this->max_iterations = max_iterations;
34 this->tolerance = tolerance;
35 this->results = Eigen::MatrixX2d(0, 2);
36 this->aitken_requirement = aitken_mode;
37 this->verbose = verbose;
38 this->derivative_or_function_g = derivative_or_function_g;
39}
40
41template <>
43 switch (this->method) {
44 case Method::NEWTON:
45 stepper = std::make_unique<NewtonRaphsonStepper<double>>(this->function, this->aitken_requirement,
46 this->derivative_or_function_g);
47 break;
49 stepper = std::make_unique<FixedPointStepper<double>>(this->function, this->aitken_requirement,
50 this->derivative_or_function_g);
51 break;
52 default:
53 std::cerr << "\033[31mCaught error: Selected method is not compatible with scalar initial guess\033[0m"
54 << std::endl;
55 break;
56 }
57}
58
59template <>
61 switch (this->method) {
63 stepper = std::make_unique<BisectionStepper<Eigen::Vector2d>>(this->function, this->aitken_requirement,
64 this->initial_guess);
65 break;
66 case Method::CHORDS:
67 stepper = std::make_unique<ChordsStepper<Eigen::Vector2d>>(this->function, this->aitken_requirement,
68 this->initial_guess);
69 break;
70 default:
71 std::cerr << "\033[31mCaught error: Selected method is not compatible with vector initial guess\033[0m"
72 << std::endl;
73 break;
74 }
75}
76
77template <typename T>
78void Solver<T>::save_results(int iter, Eigen::Vector2d result_to_save) {
79 results.conservativeResize(iter + 1, 2);
80 this->results.row(iter) = result_to_save.transpose();
81}
82
83template <typename T>
84Eigen::Vector2d Solver<T>::get_previous_result(int step_length) {
85 int target_row = results.rows() - step_length - 1;
86 return this->results.row(target_row);
87}
88
89template <>
91 if (results.rows() == 0) results.conservativeResize(1, 2);
92 this->save_results(0, {this->initial_guess, this->function(this->initial_guess)});
93}
94
95template <>
97 if (results.rows() == 0) results.resize(1, 2);
98 double to_save = initial_guess(1);
99 this->save_results(0, {to_save, this->function(to_save)});
100}
101
102template <typename T>
103double Solver<T>::calculate_error(double x_prev, double x_next) {
104 return abs(x_prev - x_next);
105}
106
107template <typename T>
108Eigen::MatrixX2d Solver<T>::solve() {
109 double err = 1.0;
110
111 std::unique_ptr<StepperBase<T>> stepper;
112
113 convert_stepper(stepper);
114
115 save_starting_point();
116
117 if (this->verbose) {
118 std::cout << "x(0): " << this->get_previous_result(0)(0) << "; f(x0): " << this->get_previous_result(0)(1)
119 << std::endl;
120 }
121
122 int iter = 1;
123
124 while (err > this->tolerance && abs(this->get_previous_result(0)(1)) > this->tolerance &&
125 iter < this->max_iterations) {
126 if (this->verbose) {
127 std::cout << "x(0): " << this->get_previous_result(0)(0) << "; f(x0): " << this->get_previous_result(0)(1)
128 << std::endl;
129 }
130 this->solver_step(iter, stepper, err);
131 }
132
133 if (iter == this->max_iterations && err > this->tolerance) {
134 std::cerr << "033[31mThe solution did not converge in" << this->max_iterations << " iterations\033[0m"
135 << std::endl;
136 }
137 if (this->verbose) {
138 if (err <= this->tolerance || abs(this->get_previous_result(0)(1)) <= this->tolerance) {
139 std::cout << "Converged in " << iter - 1 << " iterations." << std::endl;
140 }
141 }
142 std::cout << "Final estimate: x = " << this->get_previous_result(0)(0)
143 << "; f(x) = " << this->get_previous_result(0)(1) << "; error = " << err << std::endl;
144
145 return results;
146}
147
148template <typename T>
149void Solver<T>::solver_step(int& iter, std::unique_ptr<StepperBase<T>>& stepper, double& err) {
150 if (this->verbose) {
151 std::cout << "Iteration " << iter << ": ";
152 }
153 auto new_results = stepper->step(this->get_previous_result(0));
154 this->save_results(iter, new_results);
155 err = this->calculate_error(new_results(0), this->get_previous_result(1)(0));
156 ++iter;
157}
158
159template class Solver<double>;
160template class Solver<Eigen::Vector2d>;
161
162#endif // ROOT_SOLVER_HPP
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::Vector2d get_previous_result(int step_length)
Returns a row of the results' matrix.
Definition solver.hpp:84
double calculate_error(double x_prev, double x_next)
Computes the error of the latest iteration.
Definition solver.hpp:103
Solver(std::function< double(double)> fun, T initial_guess, const Method method, int max_iterations, double tolerance, bool aitken_mode, bool verbose)
Constructor for Solver object.
Definition solver.hpp:15
The virtual mother stepper class which defines constructor and method in common for all the methods.
Definition stepper_def.hpp:24
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
constexpr double tol
Definition solver.hpp:11
constexpr int max_iters
Definition solver.hpp:12
Contains definition of class Solver to find the root of a non-linear equation with some numerical met...