Two types of solvers are available. The solver itself depends only on the
dimension of the problem and the algorithm and can be reused for different problems.
The FdfSolver requires derivatives of the function to solve.
GSL::MultiRoot::FSolver.new(T, n)GSL::MultiRoot::FSolver.alloc(T, n)FSolver class of type T
for a system of n dimensions. The type is given by a constant or a string,
GSL::MultiRoot::FdfSolver.new(T, n)GSL::MultiRoot::FdfSolver.alloc(T, n)FdfSolver class of type T
for a system of n dimensions. The type is given by a constant,
GSL::MultiRoot::FSolver#set(func, x)Vector, and func
is a MultiRoot:Function object.GSL::MultiRoot::FdfSolver#set(func_fdf, x)Vector, and func_fdf
is a MultiRoot:Function_fdf object.GSL::MultiRoot::FSolver#nameGSL::MultiRoot::FdfSolver#nameGSL::MultiRoot:Function.new(proc, dim, params)See example below:
# x: vector, current guess
# params: a scalar or an array
# f: vector, function value
proc = Proc.new { |x, params, f|
a = params[0]; b = params[1]
x0 = x[0]; x1 = x[1]
f[0] = a*(1 - x0)
f[1] = b*(x1 - x0*x0)
}
params = [1.0, 10.0]
func = MultiRoot::Function.new(proc, 2, params)
fsolver = MultiRoot::FSolver.new("broyden", 2)
x = [-10, -5] # initial guess
fsolver.set(func, x)GSL::MultiRoot:Function_fdf.new(proc, dim, params)See the example below:
procf = Proc.new { |x, params, f|
a = params[0]; b = params[1]
x0 = x[0]; x1 = x[1]
f[0] = a*(1 - x0)
f[1] = b*(x1 - x0*x0)
}
procdf = Proc.new { |x, params, jac|
a = params[0]; b = params[1]
jac.set(0, 0, -a)
jac.set(0, 1, 0)
jac.set(1, 0, -2*b*x[0])
jac.set(1, 1, b)
}
params = [1.0, 10.0]
func_fdf = MultiRoot::Function_fdf.new(procf, procdf, n, params)
fdfsolver = MultiRoot::FdfSolver.new("gnewton", n)
x = [-10.0, -5.0]
fdfsolver.set(func_fdf, x)GSL::MultiRoot::FSolver#interateGSL::MultiRoot::FdfSolver#interateThese methods perform a single iteration of the solver self. If the iteration encounters an unexpected problem then an error code will be returned,
The solver maintains a current best estimate of the root at all times. This information can be accessed with the following auxiliary methods.
GSL::MultiRoot::FSolver#rootGSL::MultiRoot::FdfSolver#rootGSL::MultiRoot::FSolver#fGSL::MultiRoot::FdfSolver#ff(x) (Vector) at the current estimate
of the root for the solver self.GSL::MultiRoot::FSolver#dxGSL::MultiRoot::FdfSolver#dxGSL::MultiRoot::FSolver#test_delta(epsabs, epsrel)GSL::MultiRoot::FdfSolver#test_delta(epsabs, epsrel)This method tests for the convergence of the sequence by comparing the last step
dx with the absolute error epsabs and relative error epsrel
to the current position x.
The test returns GSL::SUCCESS if the following condition is achieved,
|dx_i| < epsabs + epsrel |x_i|
for each component of x and returns GSL::CONTINUE otherwise.
GSL::MultiRoot::FSolver#test_residual(epsabs)GSL::MultiRoot::FdfSolver#test_residual(epsabs)This method tests the residual value f against the absolute error
bound epsabs. The test returns GSL::SUCCESS if the following
condition is achieved,
sum_i |f_i| < epsabs
and returns GSL::CONTINUE otherwise. This criterion is suitable for
situations where the precise location of the root, x, is unimportant
provided a value can be found where the residual is small enough.
GSL::MultiRoot::Function#solve(x0, max_iter = 1000, eps = 1e-7, type = "hybrids")GSL::MultiRoot::FSolver#solve(max_iter = 1000, eps = 1e-7)GSL::MultiRoot::FSolver.solve(fsolver, max_iter = 1000, eps = 1e-7)See sample script samples/multiroot/fsolver3.rb.
proc = Proc.new { |x, params, f|
a = params[0]; b = params[1]
x0 = x[0]; x1 = x[1]
f[0] = a*(1 - x0)
f[1] = b*(x1 - x0*x0)
}
params = [1.0, 10.0]
func = MultiRoot::Function.new(proc, 2, params)
fsolver = MultiRoot::FSolver.new("hybrid", 2)
x = [-10, -5]
fsolver.set(func, x)
iter = 0
begin
iter += 1
status = fsolver.iterate
root = fsolver.root
f = fsolver.f
printf("iter = %3u x = % .3f % .3f f(x) = % .3e % .3e\n",
iter, root[0], root[1], f[0], f[1])
status = fsolver.test_residual(1e-7)
end while status == GSL::CONTINUE and iter < 1000
n = 2
procf = Proc.new { |x, params, f|
a = params[0]; b = params[1]
x0 = x[0]; x1 = x[1]
f[0] = a*(1 - x0)
f[1] = b*(x1 - x0*x0)
}
procdf = Proc.new { |x, params, jac|
a = params[0]; b = params[1]
jac.set(0, 0, -a)
jac.set(0, 1, 0)
jac.set(1, 0, -2*b*x[0])
jac.set(1, 1, b)
}
params = [1.0, 10.0]
f = MultiRoot::Function_fdf.new(procf, procdf, n, params)
fdfsolver = MultiRoot::FdfSolver.new("gnewton", n)
x = [-10.0, -5.0]
fdfsolver.set(f, x)
iter = 0
begin
iter += 1
status = fdfsolver.iterate
root = fdfsolver.root
f = fdfsolver.f
printf("iter = %3u x = % .3f % .3f f(x) = % .3e % .3e\n",
iter, root[0], root[1], f[0], f[1])
status = fdfsolver.test_residual(1e-7)
end while status == GSL::CONTINUE and iter < 1000