Basin

Search documentation

Search the guides, solvers, and migration docs.

  • Guide
  • Visualizer
  • Benchmarks

Documentation

  • Overview
  • Getting started
  • Migrating from Argmin
  • Migrating to Basin 2.0
  • Migrating to Basin 3.0

Solvers

  • Choosing a solver
  • First-order
    • Gradient descent
    • Nonlinear CG
    • Stochastic gradient descent
    • Projected gradient descent
  • Quasi-Newton
    • BFGS
    • L-BFGS
    • L-BFGS-B
  • Derivative-free
    • Nelder–Mead
    • MADS
    • NEWUOA
    • BOBYQA
    • LINCOA
    • COBYLA
    • Solis–Wets
  • Trust-region
    • Trust-region Newton
  • Nonlinear least squares
    • Gauss–Newton
    • Levenberg–Marquardt
    • Levenberg–Marquardt QR
    • Bounded Levenberg–Marquardt
    • Trust-region reflective
  • Global and stochastic
    • DIRECT
    • Globalized bounded Nelder–Mead
    • Simulated annealing
    • CMA-ES
    • Bounded CMA-ES
    • Differential evolution
    • Particle swarm
    • Random search
    • Steady-state genetic algorithm
    • Basin-hopping
  • Memetic
    • CMA-ES with local search
    • Bounded CMA-ES with local search
    • DE with local search
    • Local-search chains
    • CMA-ES chains
    • Solis–Wets chains
  • General constrained
    • SLSQP
    • Barrier method
    • Augmented Lagrangian
  • Scalar minimization
    • Brent
    • Brent with derivatives
    • Golden-section search
  • Root finding
    • Bisection
    • Brent
    • Secant
    • Newton
    • Halley
    • TOMS 748
Navigation

Documentation

  • Overview
  • Getting started
  • Migrating from Argmin
  • Migrating to Basin 2.0
  • Migrating to Basin 3.0

Solvers

  • Choosing a solver
  • First-order
    • Gradient descent
    • Nonlinear CG
    • Stochastic gradient descent
    • Projected gradient descent
  • Quasi-Newton
    • BFGS
    • L-BFGS
    • L-BFGS-B
  • Derivative-free
    • Nelder–Mead
    • MADS
    • NEWUOA
    • BOBYQA
    • LINCOA
    • COBYLA
    • Solis–Wets
  • Trust-region
    • Trust-region Newton
  • Nonlinear least squares
    • Gauss–Newton
    • Levenberg–Marquardt
    • Levenberg–Marquardt QR
    • Bounded Levenberg–Marquardt
    • Trust-region reflective
  • Global and stochastic
    • DIRECT
    • Globalized bounded Nelder–Mead
    • Simulated annealing
    • CMA-ES
    • Bounded CMA-ES
    • Differential evolution
    • Particle swarm
    • Random search
    • Steady-state genetic algorithm
    • Basin-hopping
  • Memetic
    • CMA-ES with local search
    • Bounded CMA-ES with local search
    • DE with local search
    • Local-search chains
    • CMA-ES chains
    • Solis–Wets chains
  • General constrained
    • SLSQP
    • Barrier method
    • Augmented Lagrangian
  • Scalar minimization
    • Brent
    • Brent with derivatives
    • Golden-section search
  • Root finding
    • Bisection
    • Brent
    • Secant
    • Newton
    • Halley
    • TOMS 748

Newton root finding

Newton’s method solves a scalar equation f(x) = 0 using its first derivative. Basin safeguards the derivative step with secant interpolation and bisection, preserving a sign-changing bracket throughout the search.

API reference

PropertyRequirement
EquationA continuous, deterministic scalar function
EvaluationsFunction values and first derivatives
SearchOne root inside a supplied bracket, with an optional guess
IntervalFinite, strictly ordered endpoints with a sign change
ParametersScalar f32 or f64, without optional features

When to use it

Consider Newton when an accurate first derivative is inexpensive, especially when it shares intermediate calculations with the function value. Near a simple root and with sufficient smoothness, Newton steps converge quadratically. Bracket safeguards can add work when the initial guess is far away or the derivative is poorly behaved.

For value-only callbacks, compare Brent or TOMS 748. If second derivatives are also cheap, compare Halley. This scalar root API is separate from trust-region Newton, which minimizes an objective using gradients and Hessians.

How it works

The first trial is the bracket midpoint unless with_initial_guess supplies another interior point. Subsequent trials propose x - f(x) / f'(x). A zero or non-finite first derivative disables that proposal. A proposal outside the bracket falls back to secant interpolation, then bisection if needed.

If two trials fail to halve the bracket, the next trial is a bisection. Each iteration evaluates one trial, updates the bracket by sign, and tests the remaining interval. The returned estimate is the evaluated endpoint with the smaller absolute residual.

The derivative method follows Boost.Math 1.89.0’s root-finding documentation. Basin adds secant fallback and the two-trial contraction safeguard, and uses bracket width for convergence.

Example

This callback computes f(x) and f'(x) together for x² - 2. The initial guess is strictly inside [0, 2].

use basin::NewtonRoot;
use std::convert::Infallible;

fn main() {
    let result = NewtonRoot::new(0.0, 2.0)
        .with_initial_guess(1.0)
        .with_absolute_position_tolerance(1e-10)
        .with_max_iter(100)
        .solve_combined(|x| Ok::<_, Infallible>((x * x - 2.0, 2.0 * x)))
        .unwrap();

    assert!(result.converged());
    assert!((result.root() - 2.0_f64.sqrt()).abs() < 1e-10);
    assert_eq!(result.function_evals(), result.callback_evals());
    assert_eq!(result.derivative_evals(), result.callback_evals());
    assert_eq!(result.second_derivative_evals(), 0);
}

Use solve when the value and derivative are separate calculations. Both callbacks return the same application error type.

use basin::NewtonRoot;
use std::convert::Infallible;

fn main() {
    let result = NewtonRoot::new(0.0, 2.0)
        .solve(
            |x| Ok::<_, Infallible>(x * x - 2.0),
            |x| Ok(2.0 * x),
        )
        .unwrap();

    assert!(result.converged());
    assert!((result.root() - 2.0_f64.sqrt()).abs() < 1e-10);
}

Practical considerations

Keep the bracket and derivatives consistent

The endpoints must be finite and strictly ordered, with finite width, and their values must have opposite signs unless one is exactly a root. The function must be deterministic and continuous, and finite at every evaluated point. Finite derivatives must describe that same function.

An explicit initial guess must be finite and strictly inside the bracket. Invalid guesses return RootError::InvalidInitialGuess before any callback, even with a zero iteration limit. If you need to discover a bracket first, see the automatic bracketing example.

Distinguish bad derivatives from callback failures

Zero or non-finite derivative values activate the safeguards. Non-finite function values are errors, and application errors from either callback are preserved in RootError::Evaluation. A callback that returns Err stops the solve; it does not request a fallback step.

A bracket excludes most even-multiplicity roots because their function values do not change sign. With several roots inside the interval, the method does not promise to find the one nearest the initial guess.

Judge convergence by the bracket

Convergence requires an exact zero or a bracket width at most absolute + relative * abs(root). A small Newton step alone does not prove convergence, and a narrow bracket does not promise a small residual. Inspect the signed value() when residual accuracy also matters.

The defaults are absolute position tolerance 1e-12, relative position tolerance 4ε for the scalar type, and 100 trial steps. The corresponding builders are with_absolute_position_tolerance, with_relative_position_tolerance, and with_max_iter. Absolute tolerance must be finite and positive, and relative tolerance must be finite and at least 4ε; invalid tolerance settings panic.

An iteration limit returns Ok with RootTerminationReason::MaxIter. Check converged() or reason(). A zero limit evaluates only the endpoints, stopping after the lower one if it is exactly a root.

Implementation

Separate callbacks evaluate derivatives only when interpolation needs them, and cache them at the current point. solve_combined obtains and caches both quantities at each function evaluation, including the endpoints. Combining callbacks can share expensive work, but also computes derivatives at points where a separate callback would not need them.

RootResult counts returned function values in function_evals() and first derivatives in derivative_evals(). callback_evals() counts actual callback invocations, so a combined value-and-derivative call counts once there. Compare callback cost alongside iteration counts when choosing an interface.

Every solve starts with fresh history and endpoint evaluations. The result retains the estimate, its signed value, the final ordered bracket, and termination. Scalar f32 and f64 require no linear-algebra backend or optional feature and work on WASM.

References

  1. Boost.Math contributors (2025). Root Finding With Derivatives: Newton-Raphson, Halley & Schroeder (Boost.Math 1.89.0). Boost. Full text.

Basin v3.1.0 — numerical optimization for Rust.

GitHub docs.rs crates.io