Report a bug
If you spot a problem with this page, click here to create a GitHub issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page.
Requires a signed-in GitHub account. This works well for small changes.
If you'd like to make larger changes you may want to consider using
a local clone.
mir.optim.least_squares
Nonlinear Least Squares Solver
Authors:
Ilya Yaroshenko
- enum
LeastSquaresStatus: int; -
maxIterations- Maximum number of iterations reached
furtherImprovement- The algorithm cann't improve the solution
xConverged- Stationary values
gConverged- Stationary gradient
fConverged- Good (small) residual
badBoundsbadGuessbadMinStepQualitybadGoodStepQualitybadStepQualitybadLambdaParamsnumericError
- template
LeastSquaresFunction(T)
templateLeastSquaresJacobian(T) - Delegates for low level D API.
- template
LeastSquaresFunctionBetterC(T) - Delegates for low level C API.
- template
LeastSquaresJacobianBetterC(T) - struct
LeastSquaresSettings(T) if (is(T == double) || is(T == float)); - Least-Squares iteration settings.
- uint
maxIterations; - Maximum number of iterations
- uint
maxAge; - Maximum jacobian model age (0 for default selection)
- T
jacobianEpsilon; - epsilon for finite difference Jacobian approximation
- T
absTolerance; - Absolute tolerance for step size, L2 norm
- T
relTolerance; - Relative tolerance for step size, L2 norm
- T
gradTolerance; - Absolute tolerance for gradient, L-inf norm
- T
maxGoodResidual; - The algorithm stops iteration when the residual value is less or equal to
maxGoodResidual. - T
maxStep; - maximum norm of iteration step
- T
maxLambda; - minimum trust region radius
- T
minLambda; - maximum trust region radius
- T
minStepQuality; - for steps below this quality, the trust region is shrinked
- T
goodStepQuality; - for steps above this quality, the trust region is expanded
- T
lambdaIncrease; - lambda is multiplied by this factor after step below min quality
- T
lambdaDecrease; - lambda is multiplied by this factor after good quality steps
- BoxQPSettings!T
qpSettings; - Bound constrained convex quadratic problem settings
- struct
LeastSquaresResult(T) if (is(T == double) || is(T == float)); - Least-Squares results.
- LeastSquaresStatus
status; - Computation status
- uint
iterations; - Successful step count
- uint
fCalls; - Number of the function calls
- uint
gCalls; - Number of the Jacobian calls
- T
residual; - Final residual
- T
lambda; - LMA variable for (inverse of) initial trust region radius
- LeastSquaresResult!T
optimize(alias f, alias g = null, alias tm = null, T)(ref scope LeastSquaresSettings!Tsettings, size_tm, Slice!(T*)x, Slice!(const(T)*)l, Slice!(const(T)*)u)
if (is(T == float) || is(T == double));
LeastSquaresResult!Toptimize(alias f, TaskPool, T)(ref scope LeastSquaresSettings!Tsettings, size_tm, Slice!(T*)x, Slice!(const(T)*)l, Slice!(const(T)*)u, TaskPooltaskPool)
if (is(T == float) || is(T == double)); - High level D API for Levenberg-Marquardt Algorithm.Computes the argmin over x of sum_i(f(x_i)^2) using the Levenberg-Marquardt algorithm, and an estimate of the Jacobian of f at x. The function f should take an input vector of length n, and fill an output vector of length
m. The function g is the Jacobian of f, and should fill a row-majormxn matrix.Throws:Parameters:f n -> mfunctiong m× n Jacobian (optional)tm thread manager for finite difference jacobian approximation in case of g is null (optional) LeastSquaresSettings!T settingsLevenberg-Marquardt data structure TaskPool taskPooltask Pool with .parallel method for finite difference jacobian approximation in case of g is null (optional) See Also:Examples:With Jacobianimport mir.ndslice.allocation: slice; import mir.ndslice.slice: sliced; import mir.blas: nrm2; LeastSquaresSettings!double settings; auto x = [100.0, 100].sliced; auto l = x.shape.slice(-double.infinity); auto u = x.shape.slice(+double.infinity); optimize!( (x, y) { y[0] = x[0]; y[1] = 2 - x[1]; }, (x, J) { J[0, 0] = 1; J[0, 1] = 0; J[1, 0] = 0; J[1, 1] = -1; }, )(settings, 2, x, l, u); assert(nrm2((x - [0, 2].sliced).slice) < 1e-8);
Examples:Using Jacobian finite difference approximation computed using in multiple threads.import mir.ndslice.allocation: slice; import mir.ndslice.slice: sliced; import mir.blas: nrm2; import std.parallelism: taskPool; LeastSquaresSettings!double settings; auto x = [-1.2, 1].sliced; auto l = x.shape.slice(-double.infinity); auto u = x.shape.slice(+double.infinity); settings.optimize!( (x, y) // Rosenbrock function { y[0] = 10 * (x[1] - x[0]^^2); y[1] = 1 - x[0]; }, )(2, x, l, u, taskPool); // import std.stdio; // writeln(settings); // writeln(x); assert(nrm2((x - [1, 1].sliced).slice) < 1e-6);
Examples:Rosenbrockimport mir.algorithm.iteration: all; import mir.ndslice.allocation: slice; import mir.ndslice.slice: Slice, sliced; import mir.blas: nrm2; LeastSquaresSettings!double settings; auto x = [-1.2, 1].sliced; auto l = x.shape.slice(-double.infinity); auto u = x.shape.slice(+double.infinity); alias rosenbrockRes = (x, y) { y[0] = 10 * (x[1] - x[0]^^2); y[1] = 1 - x[0]; }; alias rosenbrockJac = (x, J) { J[0, 0] = -20 * x[0]; J[0, 1] = 10; J[1, 0] = -1; J[1, 1] = 0; }; static class FFF { static auto opCall(Slice!(const(double)*) x, Slice!(double*, 2) J) { rosenbrockJac(x, J); } } settings.optimize!(rosenbrockRes, FFF)(2, x, l, u); // import std.stdio; // writeln(settings.iterations, " ", settings.fCalls, " ", settings.gCalls, " x = ", x); assert(nrm2((x - [1, 1].sliced).slice) < 1e-8); ///// settings = settings.init; x[] = [150.0, 150.0]; l[] = [10.0, 10.0]; u[] = [200.0, 200.0]; settings.optimize!(rosenbrockRes, rosenbrockJac)(2, x, l, u); // writeln(settings.iterations, " ", settings.fCalls, " ", settings.gCalls, " ", x); assert(nrm2((x - [10, 100].sliced).slice) < 1e-5); assert(x.all!"a >= 10");
Examples:import mir.blas: nrm2; import mir.math.common; import mir.ndslice.allocation: slice; import mir.ndslice.topology: linspace, map; import mir.ndslice.slice: sliced; import mir.random; import mir.random.algorithm; import mir.random.variable; import std.parallelism: taskPool; alias model = (x, p) => p[0] * map!exp(-x * p[1]); auto p = [1.0, 2.0]; auto xdata = [20].linspace([0.0, 10.0]); auto rng = Random(12345); auto ydata = slice(model(xdata, p) + 0.01 * rng.randomSlice(normalVar, xdata.shape)); auto x = [0.5, 0.5].sliced; auto l = x.shape.slice(-double.infinity); auto u = x.shape.slice(+double.infinity); LeastSquaresSettings!double settings; settings.optimize!((p, y) => y[] = model(xdata, p) - ydata)(ydata.length, x, l, u); assert((x - [1.0, 2.0].sliced).slice.nrm2 < 0.05);
Examples:import mir.algorithm.iteration: all; import mir.ndslice.allocation: slice; import mir.ndslice.topology: map, repeat, iota; import mir.ndslice.slice: sliced; import mir.random; import mir.random.variable; import mir.random.algorithm; import mir.math.common; alias model = (x, p) => p[0] * map!exp(-x / p[1]) + p[2]; auto xdata = iota([100], 1); auto rng = Random(12345); auto ydata = slice(model(xdata, [10.0, 10.0, 10.0]) + 0.1 * rng.randomSlice(normalVar, xdata.shape)); LeastSquaresSettings!double settings; auto x = [15.0, 15.0, 15.0].sliced; auto l = [5.0, 11.0, 5.0].sliced; auto u = x.shape.slice(+double.infinity); settings.optimize!((p, y) => y[] = model(xdata, p) - ydata) (ydata.length, x, l, u); assert(all!"a >= b"(x, l)); // import std.stdio; // writeln(x); // writeln(settings.iterations, " ", settings.fCalls, " ", settings.gCalls); settings = settings.init; x[] = [5.0, 5.0, 5.0]; l[] = -double.infinity; u[] = [15.0, 9.0, 15.0]; settings.optimize!((p, y) => y[] = model(xdata, p) - ydata) (ydata.length, x, l , u); assert(x.all!"a <= b"(u)); // writeln(x); // writeln(settings.iterations, " ", settings.fCalls, " ", settings.gCalls);
Examples:import mir.blas: nrm2; import mir.math.common: sqrt; import mir.ndslice.allocation: slice; import mir.ndslice.slice: sliced; LeastSquaresSettings!double settings; auto x = [0.001, 0.0001].sliced; auto l = [-0.5, -0.5].sliced; auto u = [0.5, 0.5].sliced; settings.optimize!( (x, y) { y[0] = sqrt(1 - (x[0] ^^ 2 + x[1] ^^ 2)); }, )(1, x, l, u); assert(nrm2((x - u).slice) < 1e-8);
- LeastSquaresResult!T
optimizeLeastSquares(alias f, alias g = null, alias tm = null, T)(ref scope LeastSquaresSettings!Tsettings, size_tm, Slice!(T*)x, Slice!(const(T)*)l, Slice!(const(T)*)u); - High level nothtow D API for Levenberg-Marquardt Algorithm.Computes the argmin over x of sum_i(f(x_i)^2) using the Least-Squares algorithm, and an estimate of the Jacobian of f at x. The function f should take an input vector of length n, and fill an output vector of length
m. The function g is the Jacobian of f, and should fill a row-majormxn matrix.Returns:optimization status.Parameters:f n -> mfunctiong m× n Jacobian (optional)tm thread manager for finite difference jacobian approximation in case of g is null (optional) LeastSquaresSettings!T settingsLevenberg-Marquardt data structure size_t mlength (dimension) of y = f( x)Slice!(T*) xinitial (in) and final (out) X value Slice!(const(T)*) llower X bound Slice!(const(T)*) uupper X bound See Also: - pure nothrow @nogc @safe string
leastSquaresStatusString(LeastSquaresStatusst); - Status string for low (extern) and middle (nothrow) levels D API.Parameters:
LeastSquaresStatus stoptimization status Returns:description for - alias
LeastSquaresTask= void delegate(uint totalThreads, uint threadId, uint i) pure nothrow @nogc @safe; - alias
LeastSquaresTaskBetterC= extern (C) void function(ref scope const(void delegate(uint, uint, uint) pure nothrow @nogc @safe), uint totalThreads, uint threadId, uint i) pure nothrow @nogc @safe; - alias
LeastSquaresThreadManager= void delegate(uint count, scope void delegate(uint totalThreads, uint threadId, uint i) pure nothrow @nogc @safe task) pure nothrow @nogc @safe; - Thread manager delegate type for low level extern(D) API.
- pure nothrow @nogc @trusted LeastSquaresResult!double
optimizeLeastSquaresD(ref scope LeastSquaresSettings!doublesettings, size_tm, Slice!(double*)x, Slice!(const(double)*)l, Slice!(const(double)*)u, Slice!(double*)work, Slice!(lapackint*)iwork, scope LeastSquaresFunction!doublef, scope LeastSquaresJacobian!doubleg= null, scope LeastSquaresThreadManagertm= null);
pure nothrow @nogc @trusted LeastSquaresResult!floatoptimizeLeastSquaresS(ref scope LeastSquaresSettings!floatsettings, size_tm, Slice!(float*)x, Slice!(const(float)*)l, Slice!(const(float)*)u, Slice!(float*)work, Slice!(lapackint*)iwork, scope LeastSquaresFunction!floatf, scope LeastSquaresJacobian!floatg= null, scope LeastSquaresThreadManagertm= null);
templateoptimizeLeastSquares(T : double)
templateoptimizeLeastSquares(T : float) - Low level extern(D) instatiation.Parameters:
LeastSquaresSettings!double settingsLevenberg-Marquardt data structure size_t mlength (dimension) of y = f(x)Slice!(double*) xinitial (in) and final (out) X value Slice!(const(double)*) llower X bound Slice!(const(double)*) uupper X bound LeastSquaresFunction!double fn -> mfunctionLeastSquaresJacobian!double gm× n Jacobian (optional)LeastSquaresThreadManager tmthread manager for finite difference jacobian approximation in case of g is null (optional) Slice!(double*) workfloating point workspace length of at least mir_least_squares_work_length Slice!(lapackint*) iworkfloating point workspace length of at least mir_least_squares_iwork_length - pure nothrow @nogc @safe size_t
mir_least_squares_work_length(size_tm, size_tn); - pure nothrow @nogc @safe size_t
mir_least_squares_iwork_length(size_tm, size_tn); - pure nothrow @nogc @trusted immutable(char)*
mir_least_squares_status_string(LeastSquaresStatusst); - Status string for extern(C) API.Parameters:
LeastSquaresStatus stoptimization status Returns:description for - alias
LeastSquaresThreadManagerBetterC= extern (C) void function(scope void* context, uint count, ref scope const(void delegate(uint, uint, uint) pure nothrow @nogc @safe) taskContext, scope extern (C) void function(ref scope const(void delegate(uint, uint, uint) pure nothrow @nogc @safe), uint totalThreads, uint threadId, uint i) pure nothrow @nogc @safe task) pure nothrow @nogc @system; - Thread manager function type for low level extern(C) API.
- pure nothrow @nogc @system LeastSquaresResult!double
mir_optimize_least_squares_d(ref scope LeastSquaresSettings!doublesettings, size_tm, size_tn, double*x, const(double)*l, const(double)*u, Slice!(double*)work, Slice!(lapackint*)iwork, scope void*fContext, scope LeastSquaresFunctionBetterC!doublef, scope void*gContext= null, scope LeastSquaresJacobianBetterC!doubleg= null, scope void*tmContext= null, scope LeastSquaresThreadManagerBetterCtm= null);
pure nothrow @nogc @system LeastSquaresResult!floatmir_optimize_least_squares_s(ref scope LeastSquaresSettings!floatsettings, size_tm, size_tn, float*x, const(float)*l, const(float)*u, Slice!(float*)work, Slice!(lapackint*)iwork, scope void*fContext, scope LeastSquaresFunctionBetterC!floatf, scope void*gContext= null, scope LeastSquaresJacobianBetterC!floatg= null, scope void*tmContext= null, scope LeastSquaresThreadManagerBetterCtm= null);
templatemir_optimize_least_squares(T : double)
templatemir_optimize_least_squares(T : float) - Low level extern(C) wrapper instatiation.Parameters:
LeastSquaresSettings!double settingsLevenberg-Marquardt data structure void* fContextcontext for the function LeastSquaresFunctionBetterC!double fn->mfunctionvoid* gContextcontext for the Jacobian (optional) LeastSquaresJacobianBetterC!double gm×nJacobian (optional)LeastSquaresThreadManagerBetterC tmthread manager for finite difference jacobian approximation in case of g is null (optional) size_t mlength (dimension) of y = f(x)size_t nlength (dimension) of X double* xinitial (in) and final (out) X value const(double)* llower X bound const(double)* uupper X bound LeastSquaresFunctionBetterC!double fn->mfunctionvoid* fContextfcontextLeastSquaresJacobianBetterC!double gm×nJacobian (optional)void* gContextgcontextLeastSquaresThreadManagerBetterC tmthread manager for finite difference jacobian approximation in case of g is null (optional) void* tmContexttmcontextSlice!(double*) workfloating point workspace length of at least mir_least_squares_work_length Slice!(lapackint*) iworkfloating point workspace length of at least mir_least_squares_iwork_length - pure nothrow @nogc @safe void
mir_least_squares_init_d(ref LeastSquaresSettings!doublesettings);
pure nothrow @nogc @safe voidmir_least_squares_init_s(ref LeastSquaresSettings!floatsettings);
templatemir_least_squares_init(T : double)
templatemir_least_squares_init(T : float) - Initialize LM data structure with default params for iteration.Parameters:
LeastSquaresSettings!double settingsLevenberg-Marquart data structure - pure nothrow @nogc @safe void
mir_least_squares_reset_d(ref LeastSquaresSettings!doublesettings);
pure nothrow @nogc @safe voidmir_least_squares_reset_s(ref LeastSquaresSettings!floatsettings);
templatemir_least_squares_reset(T : double)
templatemir_least_squares_reset(T : float) - Resets all counters and flags, fills x, y, upper, lower, vecors with default values.Parameters:
LeastSquaresSettings!double settingsLevenberg-Marquart data structure
Copyright © 2016-2020 by Ilya Yaroshenko | Page generated by
Ddoc on Mon Mar 30 12:03:10 2020