Newton devised a method to solve equations using values of the function and its first derivative. It is
implemented by the NewtonRaphsonSolver
class.
The NewtonRaphsonSolver class has two constructors. The first takes no arguments. The function
to solve and its derivative must be set using the TargetFunction and DerivativeOfTargetFunction
properties, which are both FuncT, TResult delegates. The initial
guess must be set using the InitialGuess property.
The second constructor takes these three properties as its three parameters.
NewtonRaphsonSolver solver = new NewtonRaphsonSolver();
solver.TargetFunction = Math.Sin;
solver.DerivativeOfTargetFunction = Math.Cos;
solver.InitialGuess = 4;
NewtonRaphsonSolver solver2 = new NewtonRaphsonSolver(Math.Sin, Math.Cos, 4);
The iteration can be controlled as outlined before by setting the AbsoluteTolerance,
RelativeTolerance, ConvergenceCriterion,
MaxIterations properties. The Solve method calculates the
zero of the target function:
Console.WriteLine("Newton-Raphson Solver: sin(x) = 0");
Console.WriteLine(" Initial guess: 4");
double result = solver.Solve();
Console.WriteLine(" Result: {0}", solver.Status);
Console.WriteLine(" Solution: {0}", solver.Result);
Console.WriteLine(" Estimated error: {0}", solver.EstimatedError);
Console.WriteLine(" # iterations: {0}", solver.IterationsNeeded);
When you don't have the derivative...
You can still use this class if you don't have the derivative of the target function.
In this case, use the static GetNumericalDifferentiator method of the
FunctionMath class
to create a FuncT, TResult delegate that represents the numerical
derivative of the target function.
It should be noted, however, that this technique requires significantly more function evaluations. If it is
possible to find an interval that contains the root, the preferred method is to use one of the root bracketing
solvers from the previous section.
A better alternative, if the function is simple enough to express in a single expression,
is to use automatic differentiation to have the derivative calculated for you.
To do this, you pass a lambda expression that evaluates the function to the
GetDerivative(ExpressionFuncDouble, Double)
method, which also creates a FuncT, TResult delegate.
Both techniques are illustrated below:
solver.TargetFunction = Special.BesselJ0;
var derivative1 = FunctionMath.GetNumericalDifferentiator(Special.BesselJ0);
var derivative2 = SymbolicMath.GetDerivative(x => Special.BesselJ0(x));
solver.DerivativeOfTargetFunction = derivative2;
solver.InitialGuess = 5;
Console.WriteLine("Zero of Bessel function near x=5:");
result = solver.Solve();
Console.WriteLine(" Solution: {0}", solver.Result);
Console.WriteLine(" # iterations: {0}", solver.IterationsNeeded);
solver.TargetFunction = AddressOf Special.BesselJ0
Dim derivative1 =
FunctionMath.GetNumericalDifferentiator(AddressOf Special.BesselJ0)
Dim derivative2 =
SymbolicMath.GetDerivative(Function(x) Special.BesselJ0(x))
solver.DerivativeOfTargetFunction = derivative2
solver.InitialGuess = 5
Console.WriteLine("Zero of Bessel function near x=5:")
result = solver.Solve()
Console.WriteLine(" Solution: {0}", solver.Result)
Console.WriteLine(" # iterations: {0}", solver.IterationsNeeded)
No code example is currently available or this language may not be supported.
solver.TargetFunction <- Func<_,_>(Special.BesselJ0)
let derivative1 =
FunctionMath.GetNumericalDifferentiator(Func<_,_>(Special.BesselJ0))
let derivative2 = SymbolicMath.GetDerivative(fun x -> Special.BesselJ0(x))
solver.DerivativeOfTargetFunction <- derivative2
solver.InitialGuess <- 5.0
Console.WriteLine("Zero of Bessel function near x=5:")
let result = solver.Solve()
Console.WriteLine(" Solution: 0", solver.Result)
Console.WriteLine(" # iterations: 0", solver.IterationsNeeded)
Newton, I. Methodus fluxionum et serierum infinitarum. 1664-1671.