Sage.js numerical computing

Evidence, not solver theater

Ten bounded lessons replay retained numerical evidence. Every success and failure remains fully readable without JavaScript or animation.

roots · scalar_root

A sign change is evidence, not the answer

Brent rapidly solves cos(x)=x and a separate bisection run checks the candidate, while the same stopping rule is rejected on a discontinuity by independent residual validation.

Learning objectives

  • Read a shrinking bracket from retained solver evidence.
  • Separate a solver stopping status from independent mathematical validation.
  • Compare Brent and bisection using retained accuracy and work measurements.

Method assumptions

  • Brent requires a finite sign-changing bracket.
  • Bisection uses the same bracket assumptions but guarantees halving steps.
  • The bracket-to-root implication requires continuity.
Complete Sage.js example
import math
from sagejs.numerics import find_root

result = find_root(
    lambda x: math.cos(x) - x,
    0.0,
    1.0,
    method="brent",
    trace="evaluations",
)
result

Open in Sage.js — starts a fresh browser worksheet containing this self-contained example.

optimization · curve_fit

A fitted curve is more than a parameter vector

Damped Gauss-Newton retains observations, evolving fitted values, residuals, and independent stationarity evidence.

Learning objectives

  • Inspect residual sticks as the parameter estimate changes.
  • Treat callback-domain failures as structured outcomes rather than fitted parameters.

Method assumptions

  • Residuals and finite-difference perturbations must stay in the model domain.
  • A small residual does not by itself certify parameter identifiability.
Complete Sage.js example
import math
from sagejs.numerics.optimization import curve_fit

xdata = [0.0, 1.0, 2.0, 3.0]
ydata = [2.0, 1.213061319, 0.735758882, 0.44626032]

def model(x, parameters):
    return parameters[0] * math.exp(-parameters[1] * x)

result = curve_fit(model, xdata, ydata, [1.5, 0.4], trace="iterations")
result

Open in Sage.js — starts a fresh browser worksheet containing this self-contained example.

ode · initial_value_problem

Adaptive steps should preserve the mathematics you care about

A harmonic oscillator closes its phase curve and passes sampled invariant/reference checks; an explicit method honestly exhausts its budget on a stiff tracker.

Learning objectives

  • Relate adaptive trajectory points to independent invariant checks.
  • Recognize stiffness from repeated work and a bounded failure status.

Method assumptions

  • Local error estimates are not global error bounds.
  • Explicit RK methods can be inappropriate even for smooth stiff equations.
Complete Sage.js example
import math
from sagejs.numerics.ode import solve_ivp

def oscillator(_t, state):
    return [state[1], -state[0]]

result = solve_ivp(
    oscillator,
    (0.0, 2.0 * math.pi),
    [1.0, 0.0],
    rtol=1e-8,
    atol=1e-11,
    trace="iterations",
)
result

Open in Sage.js — starts a fresh browser worksheet containing this self-contained example.

linear_algebra · solve

A solution is credible only with a scale-aware residual

Iterative refinement records improving backward error, while a singular system produces an explicit diagnostic instead of a spurious vector.

Learning objectives

  • Read normwise backward error rather than raw residual alone.
  • Distinguish singularity from an ordinary convergence failure.

Method assumptions

  • Binary64 residuals must be interpreted relative to matrix and solution scale.
  • A singular coefficient matrix does not define a unique solution.
Complete Sage.js example
from sagejs.numerics.linear_algebra import solve

A = [
    [2.7885359691576745, -9.49978489554666, -4.499413632617615],
    [-5.5357852370235445, 4.729424283280249, 3.533989748458225],
    [7.843591354096908, -8.261223347411677, -1.561563606294591],
]
b = [26.752113888947807, 25.823734998854537, -27.440931113276115]
result = solve(A, b, tolerance=2e-17, max_refinement=3, trace="iterations")
result

Open in Sage.js — starts a fresh browser worksheet containing this self-contained example.

integration · adaptive_quadrature

An error estimate is a budget allocation record

Adaptive Gauss-Kronrod exposes the retained interval partition and local error allocation; an evaluation ceiling suppresses an unvalidated partial estimate.

Learning objectives

  • See where an adaptive integrator spends its evaluations.
  • Understand why an incomplete partition is not a public integral value.

Method assumptions

  • The integrand must be finite on every evaluated point.
  • The reported error is an estimator under the method's smoothness assumptions.
Complete Sage.js example
import math
from sagejs.numerics.integration import integrate

result = integrate(
    lambda x: math.exp(-x * x),
    -2.0,
    2.0,
    absolute_tolerance=1e-10,
    relative_tolerance=1e-10,
    trace="iterations",
)
result

Open in Sage.js — starts a fresh browser worksheet containing this self-contained example.

approximation · polynomial_approximation

Representation stability and approximation quality are different

Chebyshev nodes control Runge oscillation; equispaced interpolation can be represented stably and still be a poor approximation between nodes.

Learning objectives

  • Separate stable evaluation from a good approximation design.
  • Compare retained construction stages without inventing intermediate polynomials.

Method assumptions

  • Validation at construction nodes does not bound between-node error.
  • The deterministic grid metric is evidence, not a rigorous supremum norm.
Complete Sage.js example
from sagejs.numerics.approximation import chebyshev_approximation

def runge(x):
    return 1.0 / (1.0 + 25.0 * x * x)

result = chebyshev_approximation(runge, [-1.0, 1.0], 16, trace="iterations")
result

Open in Sage.js — starts a fresh browser worksheet containing this self-contained example.

spectral · eigensystem

Eigenvalues can be available when an eigenbasis is not trustworthy

Hermitian Jacobi iterations expose decreasing off-diagonal mass; a nearly defective general matrix fails the eigenbasis conditioning gate.

Learning objectives

  • Read convergence evidence for a Hermitian eigensystem.
  • Recognize why a numerically singular eigenvector basis must be withheld.

Method assumptions

  • The successful path requires a finite Hermitian matrix.
  • A clustered nonnormal spectrum can make eigenvectors arbitrarily sensitive.
Complete Sage.js example
from sagejs.numerics.spectral import symmetric_eigen

A = [[4.0, 1.0, 0.0], [1.0, 3.0, 0.5], [0.0, 0.5, 1.0]]
result = symmetric_eigen(A, trace="iterations")
result

Open in Sage.js — starts a fresh browser worksheet containing this self-contained example.

optimization · minimize

A path explains both convergence and a budget stop

Nelder-Mead retains accepted simplex summaries on Rosenbrock's valley; the same problem with two iterations stops explicitly instead of claiming the best point is optimal.

Learning objectives

  • Follow a derivative-free path through a curved valley.
  • Distinguish a useful incumbent from a validated optimum.

Method assumptions

  • Nelder-Mead is local and supplies no global optimality proof.
  • A maximum-iteration status must not be relabeled as convergence.
Complete Sage.js example
from sagejs.numerics.optimization import minimize

def rosenbrock(point):
    x, y = point
    return (1.0 - x) ** 2 + 100.0 * (y - x * x) ** 2

result = minimize(
    rosenbrock,
    [-1.2, 1.0],
    method="bfgs",
    maxiter=200,
    gtol=1e-5,
    trace="iterations",
)
result

Open in Sage.js — starts a fresh browser worksheet containing this self-contained example.

statistics · regression

Robust fitting shows which observations lost influence

Huber regression retains weights and parameter progress for one outlier; a translated large-offset regression is rejected when independent validation cannot support its coefficients.

Learning objectives

  • Connect robust weights to visible outlier influence.
  • Treat a finite coefficient vector as provisional until scale-aware validation passes.

Method assumptions

  • Robust fitting changes the loss; it does not identify data errors automatically.
  • Binary64 regression with large offsets can lose information through cancellation.
Complete Sage.js example
from sagejs.numerics.statistics import huber_regression

x = list(range(8))
y = [1.0 + 2.0 * value for value in x]
y[-1] = 30.0
result = huber_regression(x, y, trace="iterations")
result

Open in Sage.js — starts a fresh browser worksheet containing this self-contained example.

ode · parameter_sweep

A parameter sweep is evidence, not a smooth promise

Vary a decay rate, validate every completed ODE endpoint independently, and retain a bounded failure without manufacturing a missing curve point.

Learning objectives

  • Read a sweep as ordered item-level evidence with aggregate resource accounting.
  • Compare validated numerical endpoints with the analytic decay law.
  • Distinguish a missing failed result from an interpolated or fabricated value.
  • Use Play, Pause, Step, Restart, Speed, and the slider over exact retained prefixes.

Method assumptions

  • The scalar decay model y'=-rate*y has the analytic solution y(t)=exp(-rate*t).
  • Every successful nested ODE result must retain passing independent validation evidence.
  • Sweep ordering is input ordering; animation order does not imply adaptive sampling in parameter space.
  • Failures have no plot coordinate unless the failed result retained a validated numeric value.
Complete Sage.js example
import math
from sagejs.numerics.ode import ode_problem, run_ode_parameter_sweep

def make_problem(parameter, limits):
    rate = float(parameter["rate"])
    return ode_problem(
        lambda t, y: [-rate*y[0]],
        (0.0, 2.0),
        [1.0],
        max_evaluations=limits.max_evaluations,
        max_elapsed_ms=9000,
        reference=lambda t: [math.exp(-rate*t)],
    )

result = run_ode_parameter_sweep(
    [
        {"rate": float("0.25")},
        {"rate": float("0.5")},
        {"rate": float("1.0")},
        {"rate": float("2.0")},
    ],
    make_problem,
)
result

Open in Sage.js — starts a fresh browser worksheet containing this self-contained example.