One dimensional root-finding and the solver classes

One-dimensional root finding algorithms can be divided into two classes, root bracketing and root polishing. The state for bracketing solvers is held in a GSL::Root::FSolver object. The updating procedure uses only function evaluations (not derivatives). The state for root polishing solvers is held in a GSL::Root::FdfSolver object. The updates require both the function and its derivative (hence the name fdf) to be supplied by the user.

Contents:

  1. Solver classes

  2. Methods

    1. Methods to solve equations

    2. GSL::Function_fdf class: Providing the function to solve

    3. Search Stopping Parameters

  3. Higher-level interface

  4. Example

Solver classes



Methods



Methods to solve equations





Function_fdf class

The FSolver object require an instance of the GSL::Function class, which is already introduced elsewhere. The FdfSolver which uses the root-polishing algorithm requires not only the function to solve, but also procedures to calculate the derivatives. This is given by the GSL::Function_fdf class.





Search Stopping Parameters




High-level interface




Example

This example is equivalent to the one found in the GSL manual, using the Brent's algorithm to solve the equation x^2 - 5 = 0.

#!/usr/bin/env ruby
require "gsl"

#solver = Root::FSolver.alloc("bisection")
#solver = Root::FSolver.alloc("falsepos")
solver = Root::FSolver.alloc(Root::FSolver::BRENT)
puts "using #{solver.name} method"

func = GSL::Function.alloc { |x, params|      # Define a function to solve
  a = params[0]; b = params[1]; c = params[2]
  (a*x + b)*x + c
}
expected = Math::sqrt(5.0)

func.set_params([1, 0, -5])

printf("%5s [%9s, %9s] %9s %10s %9s\n",
        "iter", "lower", "upper", "root",
        "err", "err(est)")

solver.set(func, 0.0, 5.0)              # initialize the solver
i = 1
begin
  status = solver.iterate
  r = solver.root
  xl = solver.x_lower
  xu = solver.x_upper
  status = Root.test_interval(xl, xu, 0, 0.001)   # Check convergence
  if status == GSL::SUCCESS
    printf("Converged:\n")
  end
  printf("%5d [%.7f, %.7f] %.7f %+.7f %.7f\n",
         i, xl, xu, r, r - expected, xu - xl)

  i += 1
end while status != GSL::SUCCESS

The following is an another version, using the FdfSolver with the Newton-Raphson algorithm.

#!/usr/bin/env ruby
require "gsl"

f = Proc.new { |x, params|
  a = params[0]; b = params[1]; c = params[2]
  (a*x + b)*x + c
}

df = Proc.new { |x, params|
  a = params[0]; b = params[1]
  2.0*a*x + b
}

function_fdf = Function_fdf.alloc(f, df)
params = [1, 0, -5]
function_fdf.set_params(params)

solver = Root::FdfSolver.alloc(Root::FdfSolver::NEWTON)
puts "using #{solver.name} method"

expected = Math::sqrt(5.0)
x = 5.0
solver.set(function_fdf, x)

printf("%-5s %10s %10s %10s\n", "iter", "root", "err", "err(est)")
iter = 0
begin
  iter += 1
  status = solver.iterate
  x0 = x
  x = solver.root

  status = Root::test_delta(x, x0, 0, 1e-3)

  if status == GSL::SUCCESS
    printf("Converged:\n")
  end

  printf("%5d %10.7f %+10.7f %10.7f\n", iter, x, x - expected, x - x0)
end while status != GSL::SUCCESS

prev next

Reference index top