26 inline std::pair<double, double>
find_bounds(std::function<
double(
double)> f,
double x_init,
double y_value,
double delta_x,
double precision,
27 long max_loops = 1000,
bool verbosity =
false) {
31 delta_x = abs(delta_x);
34 double eps = (y1 - y_value >= 0) ? 1.0 : -1.0;
41 for (; nbre_loop <= max_loops && (y2 - y_value) * eps > 0 && abs(y2 - y_value) > precision; ++nbre_loop) {
44 out << fmt::format(
"x={}, f(x)= {}\n", x2, y2);
70 inline std::pair<double, double>
dichotomy(std::function<
double(
double)> f,
double x_low,
double x_high,
double y_target,
double precision,
71 long max_loops, std::string x_name, std::string y_name,
bool verbosity) {
80 out << fmt::format(
"{} < {} < {}\n", x1, x_name, x2);
81 out << fmt::format(
"{} < {} < {}\n", y1, y_name, y2);
83 double yfound = (abs(y1 - y_target) < abs(y2 - y_target)) ? y1 : y2;
84 double x = (abs(y1 - y_target) < abs(y2 - y_target)) ? x1 : x2;
87 for (; nbre_loop <= max_loops && abs(yfound - y_target) > precision; ++nbre_loop) {
88 x = x1 + (x2 - x1) * (y_target - y1) / (y2 - y1);
90 if ((y1 - y_target) * (yfound - y_target) > 0) {
97 out << fmt::format(
"{} < {} < {}\n", x1, x_name, x2);
98 out << fmt::format(
"{} < {} < {}\n", y1, y_name, y2);
101 if (std::abs(yfound - y_target) < precision) {
102 out << fmt::format(
"{} found in {} iterations:\n", x_name, nbre_loop);
103 out << fmt::format(
"{} = {}; {} = {}\n", y_name, yfound, x_name, x);
106 out << fmt::format(
"FAILURE to adjust {} to the value {} after {} iterations.\n", x_name, y_target, nbre_loop);
107 throw std::runtime_error{fmt::format(
"Dichotomy adjustment for {} failed after {} iterations", x_name, nbre_loop)};
127 inline std::pair<double, double>
bisection(std::function<
double(
double)> f,
double x_low,
double x_high,
double y_target,
double precision,
128 long max_loops, std::string x_name, std::string y_name,
bool verbosity) {
132 auto y_low = f(x_low);
133 auto y_high = f(x_high);
135 out << fmt::format(
"{} < {} < {}\n", x_low, x_name, x_high);
136 out << fmt::format(
"{} < {} < {}\n", y_low, y_name, y_high);
138 for (
auto it = 0; it < max_loops; it++) {
139 auto x_mid = (x_high + x_low) / 2.0;
140 auto y_mid = f(x_mid);
142 if (abs(y_mid - y_target) <= precision)
return {x_mid, y_mid};
144 if (y_mid - y_target >= 0) {
152 out << fmt::format(
"{} < {} < {}\n", x_low, x_name, x_high);
153 out << fmt::format(
"{} < {} < {}\n", y_low, y_name, y_high);
156 out << fmt::format(
"FAILURE to adjust {} to the value {} after {} iterations.\n", x_name, y_target, max_loops);
157 throw std::runtime_error{fmt::format(
"Dichotomy adjustment for {} failed after {} iterations", x_name, max_loops)};
176 inline std::pair<double, double>
root_finder(std::string method, std::function<
double(
double)> f,
double x_init,
double y_value,
double precision,
177 double delta_x,
long max_loops = 1000, std::string x_name =
"", std::string y_name =
"",
178 bool verbosity =
false) {
182 out << fmt::format(
"Root finder search of {} to obtain {} = {} +/- {}\n", x_name, y_name, y_value, precision);
184 auto [x1, x2] =
find_bounds(f, x_init, y_value, delta_x, precision, max_loops, verbosity);
186 if (method ==
"dichotomy") {
187 return dichotomy(f, x1, x2, y_value, precision, max_loops, x_name, y_name, verbosity);
188 }
else if (method ==
"bisection") {
189 return bisection(f, x1, x2, y_value, precision, max_loops, x_name, y_name, verbosity);
191 throw std::runtime_error(
"Not a valid choice of root finder method!");
FIXME : MERGE : replace triqs::report_steam, -> merge + alias.
std::pair< double, double > find_bounds(std::function< double(double)> f, double x_init, double y_value, double delta_x, double precision, long max_loops=1000, bool verbosity=false)
find upper and lower bounds of f(x)
std::pair< double, double > dichotomy(std::function< double(double)> f, double x_low, double x_high, double y_target, double precision, long max_loops, std::string x_name, std::string y_name, bool verbosity)
dichotomy algorithm
std::pair< double, double > bisection(std::function< double(double)> f, double x_low, double x_high, double y_target, double precision, long max_loops, std::string x_name, std::string y_name, bool verbosity)
bisection algorithm
std::pair< double, double > root_finder(std::string method, std::function< double(double)> f, double x_init, double y_value, double precision, double delta_x, long max_loops=1000, std::string x_name="", std::string y_name="", bool verbosity=false)
Root finder f(x) = 0.