gleastsq

A least squares curve fitting library for Gleam. This library uses the Nx
library from Elixir under the hood to perform matrix operations.
gleastsq targets Erlang only. Nx is a BEAM dependency, so you will want a
working Erlang/Elixir toolchain available when developing locally.
Which method should I use?
The library provides four functions for curve fitting: least_squares, gauss_newton, levenberg_marquardt and trust_region_reflective.
Least Squares
Docs and examples
The least_squares function is just an alias for the levenberg_marquardt function.
Levenberg-Marquardt
Docs and examples
Ideal for non-linear least squares problems, particularly when the initial guess is far from the solution. It combines the benefits of the Gauss-Newton method and gradient descent, making it robust and efficient for various scenarios. However, it requires careful tuning of the damping parameter to balance convergence speed and stability.
Trust-Region Reflective
Docs and examples
Best suited for problems with constraints (upper and lower bounds for each function parameter), this method uses a bounded trust-region style update so each iteration stays within a controlled step size and respects the provided parameter bounds. It can be more stable than a plain Gauss-Newton step on constrained problems, but it is also more computationally intensive.
Gauss-Newton
Docs and examples
Efficient for problems where residuals are small and the initial guess is close to the true solution. It approximates the Hessian matrix, leading to faster convergence for well-behaved problems. However, it may struggle with highly non-linear problems or poor initial guesses, as it lacks the robustness of the Levenberg-Marquardt and trust-region reflective methods.
Installation and Example
gleam add gleastsq
import gleam/io
import gleastsq
fn parabola(x: Float, params: List(Float)) -> Float {
let assert [a, b, c] = params
a *. x *. x +. b *. x +. c
}
pub fn main() {
let x = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0]
let y = [0.0, 1.0, 4.0, 9.0, 16.0, 25.0]
let initial_guess = [1.0, 1.0, 1.0]
let assert Ok(result) =
gleastsq.least_squares(x, y, parabola, initial_guess, opts: [])
io.debug(result) // [1.0, 0.0, 0.0] (within numerical error)
}
Further documentation can be found at https://hexdocs.pm/gleastsq.
Validation
All fitting functions return Error(WrongParameters(_)) when x and y have
different lengths or when initial_params is empty. The
trust_region_reflective function also validates that any bound lists have the
same length as initial_params.