@tubular/math
Version:
Miscellaneous math functions
121 lines • 3.71 kB
JavaScript
import { abs } from './math';
const CGOLD = 0.381966011250105; // (3 - sqrt(5)) / 2
const ZEPS = 1.0E-20;
export class MinMaxFinder {
constructor(minMaxSeekingFunction, tolerance, maxIterations, ax, bx, cx) {
this.minMaxSeekingFunction = minMaxSeekingFunction;
this.tolerance = tolerance;
this.maxIterations = maxIterations;
this.ax = ax;
this.bx = bx;
this.cx = cx;
this._iterationCount = 0;
this.isMin = true;
}
getXAtMinMax() {
let a;
let b;
let d = 0.0;
let etemp;
let fu;
let fv;
let fw;
let p;
let q;
let r;
let tol1;
let tol2;
let u;
let v;
let w;
let x;
let xm;
let e = 0.0;
let sign = 1.0;
a = (this.ax < this.cx ? this.ax : this.cx);
b = (this.ax > this.cx ? this.ax : this.cx);
x = w = v = this.bx;
this.fx = this.minMaxSeekingFunction(x);
// Reverse the sign of the evaluated function if we're searching for a max rather than a min.
if (this.fx > this.minMaxSeekingFunction(this.ax)) {
this.isMin = false;
this.fx *= -1;
sign = -1.0;
}
else
this.isMin = true;
fw = fv = this.fx;
this._iterationCount = 0;
while (++this._iterationCount <= this.maxIterations) {
xm = 0.5 * (a + b);
tol1 = this.tolerance * abs(x) + ZEPS;
tol2 = 2.0 * tol1;
if (abs(x - xm) <= tol2 - 0.5 * (b - a)) {
this.fx *= sign;
return x;
}
if (abs(e) > tol1) {
r = (x - w) * (this.fx - fv);
q = (x - v) * (this.fx - fw);
p = (x - v) * q - (x - w) * r;
q = 2.0 * (q - r);
if (q > 0.0)
p = -p;
q = abs(q);
etemp = e;
e = d;
if (abs(p) >= abs(0.5 * q * etemp) || p <= q * (a - x) || p >= q * (b - x)) {
e = (x >= xm ? a - x : b - x);
d = CGOLD * e;
}
else {
d = p / q;
u = x + d;
if (u - a < tol2 || b - u < tol2)
d = Math.sign(xm - x) * tol1;
}
}
else {
e = (x >= xm ? a - x : b - x);
d = CGOLD * e;
}
u = (abs(d) >= tol1 ? x + d : x + Math.sign(d) * tol1);
fu = sign * this.minMaxSeekingFunction(u);
if (fu <= this.fx) {
if (u >= x)
a = x;
else
b = x;
v = w;
w = x;
x = u;
fv = fw;
fw = this.fx;
this.fx = fu;
}
else {
if (u < x)
a = u;
else
b = u;
if (fu <= fw || w === x) {
v = w;
w = u;
fv = fw;
fw = fu;
}
else if (fu <= fv || v === x || v === w) {
v = u;
fv = fu;
}
}
}
this.fx *= sign;
return x;
}
get foundMaximum() { return !this.isMin; }
get foundMinimum() { return this.isMin; }
get lastY() { return this.fx; }
get iterationCount() { return this._iterationCount; }
}
//# sourceMappingURL=min-max-finder.js.map