SciDart
Root finding
Roots of scalar functions and of systems of nonlinear equations.
Like scipy.optimize.root_scalar, scipy.optimize.root
Scalar functions
rootScalar finds x with f(x) = 0. Each method needs different arguments:
| Method | Needs | Notes |
|---|---|---|
brentq |
bracket where f changes sign |
fast, and converges for any valid bracket |
bisect |
bracket |
slower, halves the bracket each step |
newton |
x0 and the derivative fprime |
very fast near the root, can diverge far from it |
secant |
x0, optionally x1 |
no derivative needed |
Without method, rootScalar picks brentq when there is a bracket, newton when there is fprime, and secant otherwise.
import 'dart:math' as math;
import 'package:scidart/scidart.dart';
void main() {
double f(double x) => math.cos(x) - x;
var brent = rootScalar(f, bracket: [0, 1]);
print('brentq: ${brent.root} after ${brent.iterations} iterations');
var newton = rootScalar(f,
method: RootScalarMethod.newton, x0: 1, fprime: (x) => -math.sin(x) - 1);
print('newton: ${newton.root} after ${newton.iterations} iterations');
var bisect = rootScalar(f, method: RootScalarMethod.bisect, bracket: [0, 1]);
print('bisect: ${bisect.root} after ${bisect.iterations} iterations');
}
Output
brentq: 0.7390851332151559 after 7 iterations newton: 0.7390851332151607 after 5 iterations bisect: 0.7390851332147577 after 39 iterations
The result is a RootScalarResult. When a method does not converge, converged is false and message says why; it does not throw. An invalid bracket throws FormatException.
Watch each method look for the root:
Loading the interactive demo…
Systems of equations
root solves f(x) = 0 for f from R^n to R^n. The default method is lm (Levenberg-Marquardt); newton and broyden1 are also available in RootMethod. Pass a jacobian to avoid finite differences.
import 'package:scidart/numdart.dart';
import 'package:scidart/scidart.dart';
void main() {
// x^2 + y^2 = 4 and x y = 1
Array f(Array v) => Array([
v[0] * v[0] + v[1] * v[1] - 4,
v[0] * v[1] - 1,
]);
var result = root(f, Array([2, 0.5]));
print('success: ${result.success}, ${result.message}');
print('x = ${result.x.toList()}');
print('f(x) = ${result.fun.toList()}');
var broyden = root(f, Array([2, 0.5]), method: RootMethod.broyden1);
print('broyden1: ${broyden.x.toList()} in ${broyden.iterations} iterations');
}
Output
success: true, converged x = [1.931851652612349, 0.5176380901529665] f(x) = [7.827427594975234e-11, -8.28915824868659e-11] broyden1: [1.9318516525788239, 0.5176380901930494] in 5 iterations