ml-levenberg-marquardt
Version:
Curve fitting method in javascript
89 lines • 3.56 kB
JavaScript
import { isAnyArray } from 'is-any-array';
export default function checkOptions(data, options) {
const { timeout, initialValues, weights = 1, damping = 1e-2, dampingStepUp = 11, dampingStepDown = 9, maxIterations = 100, errorTolerance = 1e-7, centralDifference = false, gradientDifference = 10e-2, improvementThreshold = 1e-3, } = options;
let { minValues, maxValues } = options;
if (damping <= 0) {
throw new Error('The damping option must be a positive number');
}
else if (!data.x || !data.y) {
throw new Error('The data parameter must have x and y elements');
}
else if (!isAnyArray(data.x) ||
data.x.length < 2 ||
!isAnyArray(data.y) ||
data.y.length < 2) {
throw new Error('The data parameter elements must be an array with more than 2 points');
}
else if (data.x.length !== data.y.length) {
throw new Error('The data parameter elements must have the same size');
}
if (!(initialValues && initialValues.length > 0)) {
throw new Error('The initialValues option is mandatory and must be an array');
}
const parameters = Array.from(initialValues);
const parLen = parameters.length;
maxValues = maxValues || new Array(parLen).fill(Number.MAX_SAFE_INTEGER);
minValues = minValues || new Array(parLen).fill(Number.MIN_SAFE_INTEGER);
if (maxValues.length !== minValues.length) {
throw new Error('minValues and maxValues must be the same size');
}
const gradientDifferenceArray = getGradientDifferenceArray(gradientDifference, parameters);
const filler = getFiller(weights, data.x.length);
const checkTimeout = getCheckTimeout(timeout);
const weightSquare = Array.from({ length: data.x.length }, (_, i) => filler(i));
return {
checkTimeout,
minValues,
maxValues,
parameters,
weightSquare,
damping,
dampingStepUp,
dampingStepDown,
maxIterations,
errorTolerance,
centralDifference,
gradientDifference: gradientDifferenceArray,
improvementThreshold,
};
}
function getGradientDifferenceArray(gradientDifference, parameters) {
if (typeof gradientDifference === 'number') {
return new Array(parameters.length).fill(gradientDifference);
}
else if (isAnyArray(gradientDifference)) {
const parLen = parameters.length;
if (gradientDifference.length !== parLen) {
return new Array(parLen).fill(gradientDifference[0]);
}
return Array.from(gradientDifference);
}
throw new Error('gradientDifference should be a number or array with length equal to the number of parameters');
}
function getFiller(weights, dataLength) {
if (typeof weights === 'number') {
const value = 1 / weights ** 2;
return () => value;
}
else if (isAnyArray(weights)) {
if (weights.length < dataLength) {
const value = 1 / weights[0] ** 2;
return () => value;
}
return (i) => 1 / weights[i] ** 2;
}
throw new Error('weights should be a number or array with length equal to the number of data points');
}
function getCheckTimeout(timeout) {
if (timeout !== undefined) {
if (typeof timeout !== 'number') {
throw new Error('timeout should be a number');
}
const endTime = Date.now() + timeout * 1000;
return () => Date.now() > endTime;
}
else {
return () => false;
}
}
//# sourceMappingURL=check_options.js.map