template<typename Real>
class Utils::AlgoBracket< Real >
Class for solving \( f(x)=0 \) without the usew of derivative.
- Note
- The used algorithm is described in: I.F.D. Oliveira, R.H.C. Takahashi, An Enhancement of the Bisection Method Average Performance Preserving Minmax Optimality, ACM Transactions on Mathematical Software, vol 47, N.1, 2020
Usage simple example:
To use this class, first wrap your function in a derived class. For instance, for the function \( f(x) = x^2 - 2 \), you can define:
public:
double eval(
double x)
const override {
return x*x - 2; }
};
Abstract base class for defining mathematical functions used in the Bracket search algorithm.
Definition Utils_AlgoBracket.hh:83
virtual Real eval(Real x) const =0
Next, instantiate the function and the solver. Then, call the desired method to find the root:
Fun1 f;
real_type x_solution = solver.
eval2(
a,
b,f);
Real eval2(Real a, Real b, PFUN pfun)
Definition Utils_AlgoBracket.hh:358
Real a() const
Definition Utils_AlgoBracket.hh:443
Real b() const
Definition Utils_AlgoBracket.hh:444
If the method converges, x_solution
will contain the computed solution.
Usage Detailed Example:
To create a custom function, derive from this class and implement the required methods. Here is an example for the function \( f(x) = x^2 - 2 \):
Step 1: including headers
To use the Bracket
class, include the necessary headers:
#include "Utils_Bracket.hh"
Step 2: defining your function
Define the function for which you want to find the root. The function must take a single argument (the variable for which you're solving) and return a value.
For example, to find the root of \( \sin(x) - \frac{x}{2} = 0 \):
static real_type myFunction(real_type x) {
return sin(x) - x / 2;
}
Step 3: Creating solver instance
Create an instance of the Bracket
class to solve your function. The class provides methods to evaluate functions and find roots.
Step 4: Calling the solver
To find a root, call the eval
method with the initial guesses for the root (interval [a, b]
). Here's an example of how to set up a program to find a root:
int
main() {
real_type root = solver.
eval2(
a,
b, myFunction);
cout << "Root found: " << root << endl;
cout << "f(root) = " << myFunction(root) << endl;
return 0;
}
Step 5: Using lambda functions
You can also use lambda functions to define your function inline, which can simplify your code. Here's how to modify the previous example:
int
main() {
real_type root = solver.
eval2(
a,
b, [](real_type x) {
return sin(x) - x / 2; });
cout << "Root found: " << root << endl;
cout << "f(root) = " << sin(root) - root / 2 << endl;
return 0;
}
Step 6: Advanced usage with function parameters
If your function requires additional parameters, you can wrap it in a lambda or use std::bind
. Here's an example using std::bind
:
#include <functional>
static real_type myParameterizedFunction(real_type x, real_type
a) {
}
int
main() {
real_type parameter = -1.0;
real_type root = solver.
eval2(
a,
b, std::bind(myParameterizedFunction, std::placeholders::_1, parameter));
cout << "Root found: " << root << endl;
cout << "f(root) = " << myParameterizedFunction(root, parameter) << endl;
return 0;
}
Class for solving without the usew of derivative.
Definition Utils_AlgoBracket.hh:274
Step 7: Analyzing results
After calling the eval2
method, you can check the number of iterations, number of function evaluations, and whether the algorithm converged:
cout <<
"Iterations: " << solver.
used_iter() << endl;
cout <<
"Function Evaluations: " << solver.
num_fun_eval() << endl;
cout <<
"Converged: " << (solver.
converged() ?
"Yes" :
"No") << endl;
Integer num_fun_eval() const
Definition Utils_AlgoBracket.hh:426
bool converged() const
Definition Utils_AlgoBracket.hh:441
Integer used_iter() const
Definition Utils_AlgoBracket.hh:421