diff --git a/source/mir/optim/fit_splie.d b/source/mir/optim/fit_splie.d index 219e104..4a6d4fd 100644 --- a/source/mir/optim/fit_splie.d +++ b/source/mir/optim/fit_splie.d @@ -19,12 +19,12 @@ Params: x = fixed X values of the spline l = lower bounds for spline(X) values u = upper bounds for spline(X) values - lambda = coefficient for the integral of the squre of the second derivative + lambda = coefficient for the integral of the square of the second derivative configuration = spline configuration (optional) Returns: $(FitSplineResult) +/ FitSplineResult!T fitSpline(alias d = "a - b", T)( - scope ref LeastSquaresSettings!T settings, + scope const ref LeastSquaresSettings!T settings, scope const T[2][] points, scope const T[] x, scope const T[] l, @@ -71,9 +71,7 @@ FitSplineResult!T fitSpline(alias d = "a - b", T)( foreach (i; 1 .. x.length) { T rd = ret.spline.withTwoDerivatives(x[i])[1]; - auto one_3a = fabs(rd - ld) < T.min_normal ? 0 : (x[i] - x[i - 1]) / (rd - ld); - auto part = (rd * rd * rd - ld * ld * ld) * one_3a; - integral += part; + integral += (rd * rd + rd * ld + ld * ld) * (x[i] - x[i - 1]); ld = rd; } assert(integral >= 0); @@ -86,9 +84,10 @@ FitSplineResult!T fitSpline(alias d = "a - b", T)( return ret; } -// @safe pure +@safe pure unittest { + import mir.test; LeastSquaresSettings!double settings; @@ -101,6 +100,7 @@ unittest auto u = new double[x.length]; u[] = +double.infinity; + import mir.stdio; double[2][] points = [ [x[0] + 0.5, -0.68361541], @@ -117,23 +117,23 @@ unittest auto result = settings.fitSpline(points, x, l, u, 0); - import mir.test; foreach (i; 0 .. x.length) result.spline(x[i]).shouldApprox == y[i]; result = settings.fitSpline(points, x, l, u, 1); + // this case sensetive for numeric noise y = [ - 0.19875353860959075, - 5.937879391669947, - 7.453487834452171, - 5.1234828581238085, - 11.909020925809962, - 13.702552020227897, - 16.980081698933578, - 7.86933302057737, - 16.20347598950289, - 19.57309893410659, + 0.1971683531479794, + 5.936895050720581, + 7.451651002121712, + 5.122509287945581, + 11.908292461047825, + 13.701350302891292, + 16.97948422229589, + 7.868130112291985, + 16.20637990062554, + 19.58302823176968, ]; foreach (i; 0 .. x.length) diff --git a/source/mir/optim/least_squares.d b/source/mir/optim/least_squares.d index 54460e8..fe8a946 100644 --- a/source/mir/optim/least_squares.d +++ b/source/mir/optim/least_squares.d @@ -163,7 +163,7 @@ Params: See_also: $(LREF optimizeLeastSquares) +/ LeastSquaresResult!T optimize(alias f, alias g = null, alias tm = null, T)( - scope ref LeastSquaresSettings!T settings, + scope const ref LeastSquaresSettings!T settings, size_t m, Slice!(T*) x, Slice!(const(T)*) l, @@ -182,7 +182,7 @@ LeastSquaresResult!T optimize(alias f, alias g = null, alias tm = null, T)( /// ditto LeastSquaresResult!T optimize(alias f, TaskPool, T)( - scope ref LeastSquaresSettings!T settings, + scope const ref LeastSquaresSettings!T settings, size_t m, Slice!(T*) x, Slice!(const(T)*) l, @@ -457,7 +457,7 @@ Params: See_also: $(LREF optimize) +/ LeastSquaresResult!T optimizeLeastSquares(alias f, alias g = null, alias tm = null, T)( - scope ref LeastSquaresSettings!T settings, + scope const ref LeastSquaresSettings!T settings, size_t m, Slice!(T*) x, Slice!(const(T)*) l, @@ -520,7 +520,7 @@ LeastSquaresResult!T optimizeLeastSquares(alias f, alias g = null, alias tm = nu Status string for low (extern) and middle (nothrow) levels D API. Params: st = optimization status -Returns: description for $(LeastSquaresStatus) +Returns: description for $(LeastSquaresStatus)furtherImprovement +/ pragma(inline, false) string leastSquaresStatusString(LeastSquaresStatus st) @safe pure nothrow @nogc @@ -592,7 +592,7 @@ Params: pragma(inline, false) LeastSquaresResult!double optimizeLeastSquaresD ( - scope ref LeastSquaresSettings!double settings, + scope const ref LeastSquaresSettings!double settings, size_t m, Slice!(double*) x, Slice!(const(double)*) l, @@ -612,7 +612,7 @@ LeastSquaresResult!double optimizeLeastSquaresD pragma(inline, false) LeastSquaresResult!float optimizeLeastSquaresS ( - scope ref LeastSquaresSettings!float settings, + scope const ref LeastSquaresSettings!float settings, size_t m, Slice!(float*) x, Slice!(const(float)*) l, @@ -702,7 +702,7 @@ extern(C) @safe nothrow @nogc pragma(inline, false) LeastSquaresResult!double mir_optimize_least_squares_d ( - scope ref LeastSquaresSettings!double settings, + scope const ref LeastSquaresSettings!double settings, size_t m, size_t n, double* x, @@ -726,7 +726,7 @@ extern(C) @safe nothrow @nogc pragma(inline, false) LeastSquaresResult!float mir_optimize_least_squares_s ( - scope ref LeastSquaresSettings!float settings, + scope const ref LeastSquaresSettings!float settings, size_t m, size_t n, float* x, @@ -800,7 +800,7 @@ private: LeastSquaresResult!T optimizeLeastSquaresImplGenericBetterC(T) ( - scope ref LeastSquaresSettings!T settings, + scope const ref LeastSquaresSettings!T settings, size_t m, size_t n, T* x, @@ -874,7 +874,7 @@ LeastSquaresResult!T optimizeLeastSquaresImplGenericBetterC(T) // LM algorithm LeastSquaresResult!T optimizeLeastSquaresImplGeneric(T) ( - scope ref LeastSquaresSettings!T settings, + scope const ref LeastSquaresSettings!T settings, size_t m, Slice!(T*) x, Slice!(const(T)*) lower, @@ -940,7 +940,7 @@ LeastSquaresResult!T optimizeLeastSquaresImplGeneric(T) if (!(T.min_normal.sqrt <= lambdaDecrease && lambdaDecrease <= 1)) { status = LeastSquaresStatus.badLambdaParams; return ret; } - maxAge = maxAge ? maxAge : g ? 3 : 2 * n; + auto maxAge = settings.maxAge ? settings.maxAge : g ? 3 : 2 * n; if (!tm) tm = delegate(uint count, scope LeastSquaresTask task) pure @nogc nothrow @trusted {