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
The least_squares function is just an alias for the levenberg_marquardt function.
Levenberg-Marquardt
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
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
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.