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.

Root of a functionSolve f(x) = 0 with Brent's method, bisection, Newton or the secant method.
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.

Solve a system of nonlinear equationsFind x where f(x) = 0 for f from R^n to R^n, like scipy.optimize.root.
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

Edit this guide on GitHub