nerdamer 1.1.13 → 2.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +184 -0
- package/README.md +293 -312
- package/dist/bundle.js +2 -0
- package/dist/bundle.js.LICENSE.txt +7 -0
- package/dist/parser.js +2 -0
- package/dist/parser.js.LICENSE.txt +7 -0
- package/docs-data/parser-functions.json +1960 -0
- package/index.d.ts +10 -426
- package/output/algebra/adapters.d.ts +33 -0
- package/output/algebra/adapters.js +109 -0
- package/output/algebra/algorithms/arith.d.ts +84 -0
- package/output/algebra/algorithms/arith.js +323 -0
- package/output/algebra/algorithms/factor.d.ts +3 -0
- package/output/algebra/algorithms/factor.js +5 -0
- package/output/algebra/algorithms/factorMultivariate.d.ts +23 -0
- package/output/algebra/algorithms/factorMultivariate.js +2393 -0
- package/output/algebra/algorithms/factorUnivariate.d.ts +72 -0
- package/output/algebra/algorithms/factorUnivariate.js +1072 -0
- package/output/algebra/algorithms/gcd.d.ts +22 -0
- package/output/algebra/algorithms/gcd.js +690 -0
- package/output/algebra/algorithms/groebnerBase.d.ts +157 -0
- package/output/algebra/algorithms/groebnerBase.js +1166 -0
- package/output/algebra/algorithms/multiPoly/MultiPoly.d.ts +137 -0
- package/output/algebra/algorithms/multiPoly/MultiPoly.js +346 -0
- package/output/algebra/algorithms/poly.d.ts +228 -0
- package/output/algebra/algorithms/poly.js +1299 -0
- package/output/algebra/algorithms/rational.d.ts +17 -0
- package/output/algebra/algorithms/rational.js +115 -0
- package/output/algebra/factor/factor.d.ts +62 -0
- package/output/algebra/factor/factor.js +158 -0
- package/output/algebra/gcd/gcd.d.ts +29 -0
- package/output/algebra/gcd/gcd.js +141 -0
- package/output/algebra/groebner.d.ts +21 -0
- package/output/algebra/groebner.js +42 -0
- package/output/algebra/partfrac.d.ts +19 -0
- package/output/algebra/partfrac.js +398 -0
- package/output/algebra/polynomialize.d.ts +20 -0
- package/output/algebra/polynomialize.js +24 -0
- package/output/algebra/simplify/complexsimp.d.ts +7 -0
- package/output/algebra/simplify/complexsimp.js +24 -0
- package/output/algebra/simplify/factorCommon.d.ts +13 -0
- package/output/algebra/simplify/factorCommon.js +136 -0
- package/output/algebra/simplify/funcsimp.d.ts +26 -0
- package/output/algebra/simplify/funcsimp.js +633 -0
- package/output/algebra/simplify/invtrigrewrite.d.ts +10 -0
- package/output/algebra/simplify/invtrigrewrite.js +96 -0
- package/output/algebra/simplify/ratsimp.d.ts +21 -0
- package/output/algebra/simplify/ratsimp.js +140 -0
- package/output/algebra/simplify/simplify.d.ts +25 -0
- package/output/algebra/simplify/simplify.js +228 -0
- package/output/algebra/simplify/trigreduce.d.ts +38 -0
- package/output/algebra/simplify/trigreduce.js +424 -0
- package/output/algebra/simplify/trigrewrite.d.ts +17 -0
- package/output/algebra/simplify/trigrewrite.js +156 -0
- package/output/algebra/simplify/trigsimp.d.ts +11 -0
- package/output/algebra/simplify/trigsimp.js +369 -0
- package/output/algebra/simplify/utils.d.ts +32 -0
- package/output/algebra/simplify/utils.js +56 -0
- package/output/algebra/utils.d.ts +32 -0
- package/output/algebra/utils.js +48 -0
- package/output/api/advanced.d.ts +7 -0
- package/output/api/advanced.js +18 -0
- package/output/api/algebra.d.ts +17 -0
- package/output/api/algebra.js +32 -0
- package/output/api/assumptions.d.ts +4 -0
- package/output/api/assumptions.js +11 -0
- package/output/api/calculus.d.ts +9 -0
- package/output/api/calculus.js +21 -0
- package/output/api/core.d.ts +17 -0
- package/output/api/core.js +41 -0
- package/output/api/debug.d.ts +16 -0
- package/output/api/debug.js +23 -0
- package/output/api/parser.d.ts +85 -0
- package/output/api/parser.js +16 -0
- package/output/api/solve.d.ts +10 -0
- package/output/api/solve.js +16 -0
- package/output/api/structures.d.ts +10 -0
- package/output/api/structures.js +22 -0
- package/output/calculus/derivative/diff.d.ts +30 -0
- package/output/calculus/derivative/diff.js +238 -0
- package/output/calculus/fresnel.d.ts +16 -0
- package/output/calculus/fresnel.js +39 -0
- package/output/calculus/integrate/byParts.d.ts +18 -0
- package/output/calculus/integrate/byParts.js +339 -0
- package/output/calculus/integrate/bySubstitution.d.ts +135 -0
- package/output/calculus/integrate/bySubstitution.js +411 -0
- package/output/calculus/integrate/integrate.d.ts +38 -0
- package/output/calculus/integrate/integrate.js +652 -0
- package/output/calculus/integrate/integrationTable.d.ts +2 -0
- package/output/calculus/integrate/integrationTable.js +914 -0
- package/output/calculus/integrate/utils.d.ts +28 -0
- package/output/calculus/integrate/utils.js +96 -0
- package/output/calculus/laplace/ilaplace.d.ts +31 -0
- package/output/calculus/laplace/ilaplace.js +192 -0
- package/output/calculus/laplace/ilaplaceTable.d.ts +2 -0
- package/output/calculus/laplace/ilaplaceTable.js +200 -0
- package/output/calculus/laplace/laplace.d.ts +22 -0
- package/output/calculus/laplace/laplace.js +109 -0
- package/output/calculus/laplace/laplaceTable.d.ts +2 -0
- package/output/calculus/laplace/laplaceTable.js +187 -0
- package/output/calculus/limit/limit.d.ts +35 -0
- package/output/calculus/limit/limit.js +1183 -0
- package/output/calculus/limit/limitsTable.d.ts +2 -0
- package/output/calculus/limit/limitsTable.js +7 -0
- package/output/core/Settings.d.ts +32 -0
- package/output/core/Settings.js +68 -0
- package/output/core/adapters.d.ts +18 -0
- package/output/core/adapters.js +40 -0
- package/output/core/classes/assumption/Assumption.d.ts +218 -0
- package/output/core/classes/assumption/Assumption.js +605 -0
- package/output/core/classes/assumption/assertiveFunctions.d.ts +6 -0
- package/output/core/classes/assumption/assertiveFunctions.js +64 -0
- package/output/core/classes/assumption/assume.d.ts +90 -0
- package/output/core/classes/assumption/assume.js +145 -0
- package/output/core/classes/collection/Collection.d.ts +107 -0
- package/output/core/classes/collection/Collection.js +231 -0
- package/output/core/classes/complex/Complex.d.ts +99 -0
- package/output/core/classes/complex/Complex.js +135 -0
- package/output/core/classes/decimalSet/DecimalSet.d.ts +226 -0
- package/output/core/classes/decimalSet/DecimalSet.js +453 -0
- package/output/core/classes/dictionary/Dictionary.d.ts +102 -0
- package/output/core/classes/dictionary/Dictionary.js +213 -0
- package/output/core/classes/equation/Equation.d.ts +256 -0
- package/output/core/classes/equation/Equation.js +350 -0
- package/output/core/classes/expression/CoeffObject.d.ts +100 -0
- package/output/core/classes/expression/CoeffObject.js +198 -0
- package/output/core/classes/expression/Expression.d.ts +1674 -0
- package/output/core/classes/expression/Expression.js +2332 -0
- package/output/core/classes/expression/analysis.d.ts +25 -0
- package/output/core/classes/expression/analysis.js +218 -0
- package/output/core/classes/expression/collect.d.ts +9 -0
- package/output/core/classes/expression/collect.js +49 -0
- package/output/core/classes/expression/format.d.ts +45 -0
- package/output/core/classes/expression/format.js +217 -0
- package/output/core/classes/expression/products.d.ts +23 -0
- package/output/core/classes/expression/products.js +115 -0
- package/output/core/classes/expression/shortcuts.d.ts +35 -0
- package/output/core/classes/expression/shortcuts.js +129 -0
- package/output/core/classes/expression/traversal.d.ts +31 -0
- package/output/core/classes/expression/traversal.js +216 -0
- package/output/core/classes/expression/trig.d.ts +25 -0
- package/output/core/classes/expression/trig.js +40 -0
- package/output/core/classes/expression/utils.d.ts +52 -0
- package/output/core/classes/expression/utils.js +189 -0
- package/output/core/classes/lookupTable/LookupTable.d.ts +12 -0
- package/output/core/classes/lookupTable/LookupTable.js +55 -0
- package/output/core/classes/matrix/Matrix.d.ts +227 -0
- package/output/core/classes/matrix/Matrix.js +889 -0
- package/output/core/classes/matrix/Sylvester.d.ts +11 -0
- package/output/core/classes/matrix/Sylvester.js +54 -0
- package/output/core/classes/matrix/functions.d.ts +26 -0
- package/output/core/classes/matrix/functions.js +52 -0
- package/output/core/classes/matrix/utils.d.ts +9 -0
- package/output/core/classes/matrix/utils.js +22 -0
- package/output/core/classes/parser/Parser.d.ts +480 -0
- package/output/core/classes/parser/Parser.js +1812 -0
- package/output/core/classes/parser/Token.d.ts +58 -0
- package/output/core/classes/parser/Token.js +137 -0
- package/output/core/classes/parser/constants.d.ts +160 -0
- package/output/core/classes/parser/constants.js +227 -0
- package/output/core/classes/parser/helpers.d.ts +21 -0
- package/output/core/classes/parser/helpers.js +42 -0
- package/output/core/classes/parser/operations/add.d.ts +15 -0
- package/output/core/classes/parser/operations/add.js +238 -0
- package/output/core/classes/parser/operations/comma.d.ts +7 -0
- package/output/core/classes/parser/operations/comma.js +11 -0
- package/output/core/classes/parser/operations/compare.d.ts +21 -0
- package/output/core/classes/parser/operations/compare.js +461 -0
- package/output/core/classes/parser/operations/divide.d.ts +2 -0
- package/output/core/classes/parser/operations/divide.js +72 -0
- package/output/core/classes/parser/operations/functions.d.ts +46 -0
- package/output/core/classes/parser/operations/functions.js +430 -0
- package/output/core/classes/parser/operations/multiply.d.ts +11 -0
- package/output/core/classes/parser/operations/multiply.js +321 -0
- package/output/core/classes/parser/operations/power.d.ts +48 -0
- package/output/core/classes/parser/operations/power.js +673 -0
- package/output/core/classes/parser/operations/subtract.d.ts +3 -0
- package/output/core/classes/parser/operations/subtract.js +35 -0
- package/output/core/classes/parser/preprocess.d.ts +14 -0
- package/output/core/classes/parser/preprocess.js +259 -0
- package/output/core/classes/parser/scripting/controlFlow.d.ts +121 -0
- package/output/core/classes/parser/scripting/controlFlow.js +355 -0
- package/output/core/classes/parser/scripting/evaluate.d.ts +10 -0
- package/output/core/classes/parser/scripting/evaluate.js +112 -0
- package/output/core/classes/parser/scripting/functions.d.ts +14 -0
- package/output/core/classes/parser/scripting/functions.js +59 -0
- package/output/core/classes/parser/scripting/scope.d.ts +35 -0
- package/output/core/classes/parser/scripting/scope.js +155 -0
- package/output/core/classes/parser/types.d.ts +125 -0
- package/output/core/classes/parser/types.js +2 -0
- package/output/core/classes/parser/wrappers/IndexedReference.d.ts +31 -0
- package/output/core/classes/parser/wrappers/IndexedReference.js +68 -0
- package/output/core/classes/parser/wrappers/KeyValuePair.d.ts +24 -0
- package/output/core/classes/parser/wrappers/KeyValuePair.js +51 -0
- package/output/core/classes/polynomial/Polynomial.d.ts +500 -0
- package/output/core/classes/polynomial/Polynomial.js +1149 -0
- package/output/core/classes/polynomial/Term.d.ts +222 -0
- package/output/core/classes/polynomial/Term.js +430 -0
- package/output/core/classes/polynomial/functions.d.ts +69 -0
- package/output/core/classes/polynomial/functions.js +126 -0
- package/output/core/classes/polynomial/utils.d.ts +62 -0
- package/output/core/classes/polynomial/utils.js +206 -0
- package/output/core/classes/rational/Rational.d.ts +504 -0
- package/output/core/classes/rational/Rational.js +779 -0
- package/output/core/classes/seq/SEQ.d.ts +13 -0
- package/output/core/classes/seq/SEQ.js +137 -0
- package/output/core/classes/valuesSet/ValuesSet.d.ts +179 -0
- package/output/core/classes/valuesSet/ValuesSet.js +381 -0
- package/output/core/classes/vector/Vector.d.ts +222 -0
- package/output/core/classes/vector/Vector.js +497 -0
- package/output/core/classes/vector/functions.d.ts +28 -0
- package/output/core/classes/vector/functions.js +47 -0
- package/output/core/common/classes/MathematicalAggregate.d.ts +53 -0
- package/output/core/common/classes/MathematicalAggregate.js +140 -0
- package/output/core/common/classes/Scope.d.ts +62 -0
- package/output/core/common/classes/Scope.js +122 -0
- package/output/core/common/classes/StructuredEntity.d.ts +55 -0
- package/output/core/common/classes/StructuredEntity.js +151 -0
- package/output/core/common/common.d.ts +63 -0
- package/output/core/common/common.js +279 -0
- package/output/core/common/functions/functions.d.ts +14 -0
- package/output/core/common/functions/functions.js +33 -0
- package/output/core/common/functions/structuredEntityUtils.d.ts +27 -0
- package/output/core/common/functions/structuredEntityUtils.js +40 -0
- package/output/core/converters/BaseConverter.d.ts +97 -0
- package/output/core/converters/BaseConverter.js +405 -0
- package/output/core/converters/Converter.d.ts +111 -0
- package/output/core/converters/Converter.js +802 -0
- package/output/core/converters/Pattern.d.ts +71 -0
- package/output/core/converters/Pattern.js +302 -0
- package/output/core/dispatch.d.ts +34 -0
- package/output/core/dispatch.js +304 -0
- package/output/core/errors.d.ts +531 -0
- package/output/core/errors.js +621 -0
- package/output/core/functions/bigint/bigint.d.ts +121 -0
- package/output/core/functions/bigint/bigint.js +392 -0
- package/output/core/functions/bigint/primeFactor.d.ts +49 -0
- package/output/core/functions/bigint/primeFactor.js +267 -0
- package/output/core/functions/bigint/primes.d.ts +1 -0
- package/output/core/functions/bigint/primes.js +11 -0
- package/output/core/functions/build/definitions.d.ts +12 -0
- package/output/core/functions/build/definitions.js +133 -0
- package/output/core/functions/build/index.d.ts +32 -0
- package/output/core/functions/build/index.js +136 -0
- package/output/core/functions/complex.d.ts +90 -0
- package/output/core/functions/complex.js +482 -0
- package/output/core/functions/decimal.d.ts +24 -0
- package/output/core/functions/decimal.js +664 -0
- package/output/core/functions/expand/expand.d.ts +42 -0
- package/output/core/functions/expand/expand.js +376 -0
- package/output/core/functions/fresnelNumeric.d.ts +12 -0
- package/output/core/functions/fresnelNumeric.js +123 -0
- package/output/core/functions/numeric.d.ts +140 -0
- package/output/core/functions/numeric.js +790 -0
- package/output/core/functions/rationalNormalization.d.ts +11 -0
- package/output/core/functions/rationalNormalization.js +117 -0
- package/output/core/functions/setFunction.d.ts +19 -0
- package/output/core/functions/setFunction.js +75 -0
- package/output/core/functions/string.d.ts +26 -0
- package/output/core/functions/string.js +101 -0
- package/output/core/functions/subst.d.ts +90 -0
- package/output/core/functions/subst.js +498 -0
- package/output/core/functions/utils.d.ts +24 -0
- package/output/core/functions/utils.js +51 -0
- package/output/core/types.d.ts +48 -0
- package/output/core/types.js +2 -0
- package/output/index.d.ts +339 -0
- package/output/index.js +715 -0
- package/output/math/defint/defintDecimal.d.ts +37 -0
- package/output/math/defint/defintDecimal.js +320 -0
- package/output/math/defint/defintNative.d.ts +57 -0
- package/output/math/defint/defintNative.js +292 -0
- package/output/math/geometry.d.ts +8 -0
- package/output/math/geometry.js +32 -0
- package/output/math/math.d.ts +655 -0
- package/output/math/math.js +1811 -0
- package/output/math/trig.d.ts +518 -0
- package/output/math/trig.js +1444 -0
- package/output/math/trunc.d.ts +19 -0
- package/output/math/trunc.js +36 -0
- package/output/math/utils.d.ts +60 -0
- package/output/math/utils.js +180 -0
- package/output/solve/classes/DecimalMatrix.d.ts +17 -0
- package/output/solve/classes/DecimalMatrix.js +86 -0
- package/output/solve/classes/FunctionSolver.d.ts +135 -0
- package/output/solve/classes/FunctionSolver.js +433 -0
- package/output/solve/classes/MultivariateSolver.d.ts +84 -0
- package/output/solve/classes/MultivariateSolver.js +240 -0
- package/output/solve/classes/PolynomialSolver.d.ts +85 -0
- package/output/solve/classes/PolynomialSolver.js +292 -0
- package/output/solve/classes/SolutionSet.d.ts +153 -0
- package/output/solve/classes/SolutionSet.js +357 -0
- package/output/solve/classes/Solver.d.ts +17 -0
- package/output/solve/classes/Solver.js +132 -0
- package/output/solve/classes/SymbolicSolver.d.ts +74 -0
- package/output/solve/classes/SymbolicSolver.js +601 -0
- package/output/solve/linsolve.d.ts +51 -0
- package/output/solve/linsolve.js +225 -0
- package/output/solve/solve.d.ts +34 -0
- package/output/solve/solve.js +260 -0
- package/output/solve/solveSystem.d.ts +31 -0
- package/output/solve/solveSystem.js +290 -0
- package/output/solve/utils.d.ts +9 -0
- package/output/solve/utils.js +62 -0
- package/output/utils/array.d.ts +42 -0
- package/output/utils/array.js +98 -0
- package/output/utils/debug.d.ts +131 -0
- package/output/utils/debug.js +295 -0
- package/output/utils/decimal.d.ts +3 -0
- package/output/utils/decimal.js +16 -0
- package/output/utils/numeric.d.ts +14 -0
- package/output/utils/numeric.js +51 -0
- package/output/utils/object.d.ts +26 -0
- package/output/utils/object.js +56 -0
- package/package.json +213 -57
- package/.travis.yml +0 -3
- package/Algebra.js +0 -4568
- package/BREAKING_CHANGES.md +0 -5
- package/CODE_OF_CONDUCT.md +0 -46
- package/CONTRIBUTING.md +0 -14
- package/Calculus.js +0 -2675
- package/Extra.js +0 -622
- package/Solve.js +0 -1783
- package/all.js +0 -16
- package/all.min.js +0 -1
- package/gulpfile.js +0 -16
- package/index.html +0 -158
- package/license.txt +0 -19
- package/nerdamer.core.js +0 -12510
- package/spec/LaTeX.spec.js +0 -302
- package/spec/TeXConvert.spec.js +0 -8
- package/spec/algebra.spec.js +0 -287
- package/spec/basic_parser.spec.js +0 -134
- package/spec/build.spec.js +0 -131
- package/spec/calculus.spec.js +0 -183
- package/spec/core.spec.js +0 -2970
- package/spec/extra.spec.js +0 -54
- package/spec/solve.spec.js +0 -126
- package/spec/support/jasmine.json +0 -11
- package/spec/support/utils.js +0 -42
- package/spec/text.spec.js +0 -132
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.FunctionSolver = void 0;
|
|
7
|
+
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
8
|
+
const Expression_1 = require("../../core/classes/expression/Expression");
|
|
9
|
+
const errors_1 = require("../../core/errors");
|
|
10
|
+
const DEFAULT_LOWER_BOUND = -100;
|
|
11
|
+
const DEFAULT_UPPER_BOUND = 100;
|
|
12
|
+
const DEFAULT_DERIVATIVE_STEP = 1e-15;
|
|
13
|
+
const DEFAULT_MAX_ITERATIONS = 200;
|
|
14
|
+
const DEFAULT_STEP_SIZE = 0.1;
|
|
15
|
+
const DEFAULT_TOLERANCE = 1e-14;
|
|
16
|
+
const DEFAULT_MAX_ROOTS = 20;
|
|
17
|
+
const BRENT_METHOD = 'Brent';
|
|
18
|
+
const NEWTON_RAPHSON_METHOD = 'NewtonRaphson';
|
|
19
|
+
const DEFAULT_ROOT_FINDING_METHOD = BRENT_METHOD;
|
|
20
|
+
/**
|
|
21
|
+
* Searches a fixed interval for real roots of a univariate expression.
|
|
22
|
+
*
|
|
23
|
+
* @remarks
|
|
24
|
+
* {@link roots} scans the configured interval from its center toward both
|
|
25
|
+
* endpoints. It refines sign-changing intervals with Brent's method or
|
|
26
|
+
* Newton-Raphson, verifies residuals, merges nearby results, and returns roots
|
|
27
|
+
* in ascending order. This is a heuristic search: an even-multiplicity root
|
|
28
|
+
* can be missed unless a scan point lands sufficiently close to it, and
|
|
29
|
+
* periodic functions are limited by both the interval and `maxRoots`.
|
|
30
|
+
*
|
|
31
|
+
* Calculations use the ambient `decimal.js` precision. An Expression supplied
|
|
32
|
+
* to the constructor is retained rather than copied, and the public settings
|
|
33
|
+
* may be adjusted before a search.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* const solver = new FunctionSolver('cos(x)-x', 'x', {
|
|
38
|
+
* lowerBound: 0,
|
|
39
|
+
* upperBound: 1,
|
|
40
|
+
* });
|
|
41
|
+
* const roots = solver.roots();
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
class FunctionSolver {
|
|
45
|
+
derivativeStep;
|
|
46
|
+
func;
|
|
47
|
+
lowerBound;
|
|
48
|
+
maxIters;
|
|
49
|
+
maxRoots;
|
|
50
|
+
method;
|
|
51
|
+
stepSize;
|
|
52
|
+
tolerance;
|
|
53
|
+
upperBound;
|
|
54
|
+
variable;
|
|
55
|
+
verbose;
|
|
56
|
+
/**
|
|
57
|
+
* Creates a real-root solver for the configured search interval.
|
|
58
|
+
*
|
|
59
|
+
* @param func - Expression to evaluate, or a string parsed as an Expression.
|
|
60
|
+
* @param variable - Variable to substitute. When omitted, the expression must
|
|
61
|
+
* contain at most one variable.
|
|
62
|
+
* @param options - Search interval, refinement method, and tolerances.
|
|
63
|
+
* @throws {@link core!UnsupportedOperationError} If `variable` is omitted and the
|
|
64
|
+
* expression contains more than one variable.
|
|
65
|
+
*/
|
|
66
|
+
constructor(func, variable, options = {}) {
|
|
67
|
+
this.func = typeof func === 'string' ? Expression_1.Expression.create(func) : func;
|
|
68
|
+
this.lowerBound = new decimal_js_1.default(options.lowerBound ?? DEFAULT_LOWER_BOUND);
|
|
69
|
+
this.upperBound = new decimal_js_1.default(options.upperBound ?? DEFAULT_UPPER_BOUND);
|
|
70
|
+
this.derivativeStep = new decimal_js_1.default(options.derivativeStep ?? DEFAULT_DERIVATIVE_STEP);
|
|
71
|
+
this.maxIters = options.maxIterations ?? DEFAULT_MAX_ITERATIONS;
|
|
72
|
+
this.variable = variable ?? this.getVariable();
|
|
73
|
+
this.stepSize = options.stepSize ?? DEFAULT_STEP_SIZE;
|
|
74
|
+
this.tolerance = new decimal_js_1.default(options.tolerance ?? DEFAULT_TOLERANCE);
|
|
75
|
+
this.maxRoots = options.maxRoots ?? DEFAULT_MAX_ROOTS;
|
|
76
|
+
this.verbose = options.verbose ?? false;
|
|
77
|
+
this.method = options.method ?? DEFAULT_ROOT_FINDING_METHOD;
|
|
78
|
+
}
|
|
79
|
+
calculateIntervals() {
|
|
80
|
+
const lower = this.lowerBound;
|
|
81
|
+
const upper = this.upperBound;
|
|
82
|
+
const step = new decimal_js_1.default(this.stepSize);
|
|
83
|
+
const length = upper.minus(lower);
|
|
84
|
+
const center = lower.plus(length.dividedBy(2).floor());
|
|
85
|
+
let x = center;
|
|
86
|
+
let u = center;
|
|
87
|
+
const intervals = [];
|
|
88
|
+
const lowerDistance = center.minus(lower);
|
|
89
|
+
const upperDistance = upper.minus(center);
|
|
90
|
+
const maxInterval = lowerDistance.greaterThan(upperDistance)
|
|
91
|
+
? lowerDistance
|
|
92
|
+
: upperDistance;
|
|
93
|
+
for (let offset = new decimal_js_1.default(0); offset.lessThan(maxInterval); offset = offset.plus(step)) {
|
|
94
|
+
const y = x.minus(step);
|
|
95
|
+
const v = u.plus(step);
|
|
96
|
+
// Add the lower interval if it is still within bounds.
|
|
97
|
+
if (y.greaterThanOrEqualTo(lower)) {
|
|
98
|
+
intervals.push([x, y]);
|
|
99
|
+
}
|
|
100
|
+
// Add the upper interval if it is still within bounds.
|
|
101
|
+
if (v.lessThanOrEqualTo(upper)) {
|
|
102
|
+
intervals.push([u, v]);
|
|
103
|
+
}
|
|
104
|
+
x = y;
|
|
105
|
+
u = v;
|
|
106
|
+
}
|
|
107
|
+
return intervals;
|
|
108
|
+
}
|
|
109
|
+
getVariable() {
|
|
110
|
+
const variables = this.func.variables();
|
|
111
|
+
// This function can only handle univariate function
|
|
112
|
+
if (variables.length > 1) {
|
|
113
|
+
throw new errors_1.UnsupportedOperationError((0, errors_1.message)('univariateInputOnly'));
|
|
114
|
+
}
|
|
115
|
+
return variables[0];
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Refines a bracket using Brent's combination of bisection, secant, and
|
|
119
|
+
* inverse-quadratic interpolation.
|
|
120
|
+
*
|
|
121
|
+
* @param a - First bracket endpoint.
|
|
122
|
+
* @param b - Second bracket endpoint.
|
|
123
|
+
* @returns Refinement metadata. Invalid brackets and exhausted iterations are
|
|
124
|
+
* represented in the returned {@link Root}; they are not thrown.
|
|
125
|
+
*/
|
|
126
|
+
Brent(a, b) {
|
|
127
|
+
// Convert inputs to Decimal
|
|
128
|
+
let aVal = new decimal_js_1.default(a);
|
|
129
|
+
let bVal = new decimal_js_1.default(b);
|
|
130
|
+
const tol = this.tolerance;
|
|
131
|
+
let fa = this.evaluate(aVal);
|
|
132
|
+
let fb = this.evaluate(bVal);
|
|
133
|
+
const error = new decimal_js_1.default(Infinity);
|
|
134
|
+
// Check if root is at endpoint
|
|
135
|
+
if (fa.abs().lessThan(tol)) {
|
|
136
|
+
return {
|
|
137
|
+
root: aVal,
|
|
138
|
+
iterations: 0,
|
|
139
|
+
converged: false,
|
|
140
|
+
error: error,
|
|
141
|
+
errorMsg: (0, errors_1.message)('endPointIsRoot'),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
if (fb.abs().lessThan(tol)) {
|
|
145
|
+
return {
|
|
146
|
+
root: bVal,
|
|
147
|
+
iterations: 0,
|
|
148
|
+
converged: true,
|
|
149
|
+
error: error,
|
|
150
|
+
errorMsg: (0, errors_1.message)('endPointIsRoot'),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
const x = fa.times(fb);
|
|
154
|
+
// Ensure f(a) and f(b) have opposite signs
|
|
155
|
+
if (x.greaterThan(0)) {
|
|
156
|
+
return {
|
|
157
|
+
root: x,
|
|
158
|
+
iterations: 0,
|
|
159
|
+
converged: true,
|
|
160
|
+
error: error,
|
|
161
|
+
errorMsg: (0, errors_1.message)('differentSignsAtEndPointsRequired'),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
// Ensure |f(a)| >= |f(b)|
|
|
165
|
+
if (fa.abs().lessThan(fb.abs())) {
|
|
166
|
+
[aVal, bVal] = [bVal, aVal];
|
|
167
|
+
[fa, fb] = [fb, fa];
|
|
168
|
+
}
|
|
169
|
+
let c = aVal;
|
|
170
|
+
let fc = fa;
|
|
171
|
+
let mflag = true;
|
|
172
|
+
let d = new decimal_js_1.default(0);
|
|
173
|
+
for (let iter = 0; iter < this.maxIters; iter++) {
|
|
174
|
+
let s;
|
|
175
|
+
// Use inverse quadratic interpolation if f(a), f(b), f(c) are distinct
|
|
176
|
+
if (!fa.equals(fc) && !fb.equals(fc)) {
|
|
177
|
+
s = aVal
|
|
178
|
+
.times(fb)
|
|
179
|
+
.times(fc)
|
|
180
|
+
.dividedBy(fa.minus(fb).times(fa.minus(fc)))
|
|
181
|
+
.plus(bVal
|
|
182
|
+
.times(fa)
|
|
183
|
+
.times(fc)
|
|
184
|
+
.dividedBy(fb.minus(fa).times(fb.minus(fc))))
|
|
185
|
+
.plus(c
|
|
186
|
+
.times(fa)
|
|
187
|
+
.times(fb)
|
|
188
|
+
.dividedBy(fc.minus(fa).times(fc.minus(fb))));
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
// Use secant method
|
|
192
|
+
s = bVal.minus(fb.times(bVal.minus(aVal)).dividedBy(fb.minus(fa)));
|
|
193
|
+
}
|
|
194
|
+
// Conditions for bisection
|
|
195
|
+
const condition1 = s.lessThan(new decimal_js_1.default(3).times(aVal).plus(bVal).dividedBy(4)) ||
|
|
196
|
+
s.greaterThan(bVal);
|
|
197
|
+
const condition2 = mflag && s.minus(bVal).abs().greaterThanOrEqualTo(bVal.minus(c).abs().dividedBy(2));
|
|
198
|
+
const condition3 = !mflag && s.minus(bVal).abs().greaterThanOrEqualTo(c.minus(d).abs().dividedBy(2));
|
|
199
|
+
const condition4 = mflag && bVal.minus(c).abs().lessThan(tol);
|
|
200
|
+
const condition5 = !mflag && c.minus(d).abs().lessThan(tol);
|
|
201
|
+
if (condition1 || condition2 || condition3 || condition4 || condition5) {
|
|
202
|
+
// Use bisection
|
|
203
|
+
s = aVal.plus(bVal).dividedBy(2);
|
|
204
|
+
mflag = true;
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
mflag = false;
|
|
208
|
+
}
|
|
209
|
+
const fs = this.evaluate(s);
|
|
210
|
+
d = c;
|
|
211
|
+
c = bVal;
|
|
212
|
+
fc = fb;
|
|
213
|
+
// Update interval
|
|
214
|
+
if (fa.times(fs).lessThan(0)) {
|
|
215
|
+
bVal = s;
|
|
216
|
+
fb = fs;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
aVal = s;
|
|
220
|
+
fa = fs;
|
|
221
|
+
}
|
|
222
|
+
// Ensure |f(a)| >= |f(b)|
|
|
223
|
+
if (fa.abs().lessThan(fb.abs())) {
|
|
224
|
+
[aVal, bVal] = [bVal, aVal];
|
|
225
|
+
[fa, fb] = [fb, fa];
|
|
226
|
+
}
|
|
227
|
+
const conditionA = fb.abs().lessThan(tol);
|
|
228
|
+
const conditionB = bVal.minus(aVal).abs().lessThan(tol);
|
|
229
|
+
// Check convergence
|
|
230
|
+
if (conditionA || conditionB) {
|
|
231
|
+
return {
|
|
232
|
+
root: bVal,
|
|
233
|
+
iterations: iter,
|
|
234
|
+
converged: true,
|
|
235
|
+
error: conditionA ? fb.abs().minus(tol) : bVal.minus(aVal).abs(),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
root: x,
|
|
241
|
+
iterations: this.maxIters,
|
|
242
|
+
converged: false,
|
|
243
|
+
error: error,
|
|
244
|
+
errorMsg: (0, errors_1.message)('convergenceFailed', { iter: String(this.maxIters) }),
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
/** Approximates the derivative with a central difference. */
|
|
248
|
+
df(x, h) {
|
|
249
|
+
const xPlusH = x.plus(h);
|
|
250
|
+
const xMinusH = x.minus(h);
|
|
251
|
+
const fPlusH = this.evaluate(xPlusH);
|
|
252
|
+
const fMinusH = this.evaluate(xMinusH);
|
|
253
|
+
// Central difference formula: (f(x+h) - f(x-h)) / (2h)
|
|
254
|
+
return fPlusH.minus(fMinusH).dividedBy(h.times(2));
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Evaluates the configured expression at a real value.
|
|
258
|
+
*
|
|
259
|
+
* @throws {@link core!UnexpectedInputError} If evaluation does not produce a scalar
|
|
260
|
+
* Expression.
|
|
261
|
+
*/
|
|
262
|
+
evaluate(at) {
|
|
263
|
+
const value = this.func.evaluate({ [this.variable]: at });
|
|
264
|
+
if (!Expression_1.Expression.isExpression(value)) {
|
|
265
|
+
throw new errors_1.UnexpectedInputError((0, errors_1.message)('unsupportedType'));
|
|
266
|
+
}
|
|
267
|
+
if (!value.isNUM()) {
|
|
268
|
+
throw new errors_1.UnexpectedInputError((0, errors_1.message)('wrongInput', {
|
|
269
|
+
expected: 'a real numeric value',
|
|
270
|
+
received: value.text(),
|
|
271
|
+
}));
|
|
272
|
+
}
|
|
273
|
+
return value.getMultiplier().toDecimal();
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Refines a root from an initial guess using Newton-Raphson and a numerical
|
|
277
|
+
* derivative.
|
|
278
|
+
*
|
|
279
|
+
* @returns Refinement metadata, including non-convergence or a zero derivative.
|
|
280
|
+
*/
|
|
281
|
+
NewtonRaphson(guess) {
|
|
282
|
+
const tol = this.tolerance;
|
|
283
|
+
const h = new decimal_js_1.default(this.derivativeStep);
|
|
284
|
+
let x = new decimal_js_1.default(guess);
|
|
285
|
+
let iterations = 0;
|
|
286
|
+
let error = new decimal_js_1.default(Infinity);
|
|
287
|
+
for (let i = 0; i < this.maxIters; i++) {
|
|
288
|
+
const fx = this.evaluate(x);
|
|
289
|
+
const fpx = this.df(x, h);
|
|
290
|
+
// Check for zero derivative (would cause division by zero)
|
|
291
|
+
if (fpx.isZero()) {
|
|
292
|
+
return {
|
|
293
|
+
root: x,
|
|
294
|
+
iterations: i,
|
|
295
|
+
converged: false,
|
|
296
|
+
error: fx.abs(),
|
|
297
|
+
errorMsg: (0, errors_1.message)('zeroDerivative', { x: x.toString() }),
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
// Newton-Raphson update: x_new = x - f(x) / f'(x)
|
|
301
|
+
const xNew = x.minus(fx.dividedBy(fpx));
|
|
302
|
+
// Calculate error as the absolute difference between iterations
|
|
303
|
+
error = xNew.minus(x).abs();
|
|
304
|
+
iterations = i + 1;
|
|
305
|
+
// Check for convergence
|
|
306
|
+
if (error.lessThanOrEqualTo(tol)) {
|
|
307
|
+
return {
|
|
308
|
+
root: xNew,
|
|
309
|
+
iterations,
|
|
310
|
+
converged: true,
|
|
311
|
+
error,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
x = xNew;
|
|
315
|
+
}
|
|
316
|
+
// Did not converge within max iterations
|
|
317
|
+
return {
|
|
318
|
+
root: x,
|
|
319
|
+
iterations,
|
|
320
|
+
converged: false,
|
|
321
|
+
error,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Searches the configured interval for real roots.
|
|
326
|
+
*
|
|
327
|
+
* @returns Verified, deduplicated roots in ascending order, limited by
|
|
328
|
+
* `maxRoots`. Failed evaluations and failed refinements are skipped.
|
|
329
|
+
*/
|
|
330
|
+
roots() {
|
|
331
|
+
const bVal = this.upperBound;
|
|
332
|
+
const tol = this.tolerance;
|
|
333
|
+
const roots = [];
|
|
334
|
+
let exit = false;
|
|
335
|
+
const evaluationCache = new Map();
|
|
336
|
+
const evaluatePoint = (point) => {
|
|
337
|
+
const key = point.toString();
|
|
338
|
+
let value = evaluationCache.get(key);
|
|
339
|
+
if (value === undefined) {
|
|
340
|
+
value = this.evaluate(point);
|
|
341
|
+
evaluationCache.set(key, value);
|
|
342
|
+
}
|
|
343
|
+
return value;
|
|
344
|
+
};
|
|
345
|
+
const addRoot = (root) => {
|
|
346
|
+
if (this.evaluate(root).abs().lessThan(tol)) {
|
|
347
|
+
roots.push(root);
|
|
348
|
+
}
|
|
349
|
+
// Check if the maximum number of roots was reached. If so we're done
|
|
350
|
+
if (roots.length >= this.maxRoots) {
|
|
351
|
+
exit = true;
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
const intervals = this.calculateIntervals();
|
|
355
|
+
for (const interval of intervals) {
|
|
356
|
+
if (exit) {
|
|
357
|
+
return roots.sort((a, b) => a.comparedTo(b)).map(x => Expression_1.Expression.create(x));
|
|
358
|
+
}
|
|
359
|
+
try {
|
|
360
|
+
const x1 = new decimal_js_1.default(interval[0]);
|
|
361
|
+
const x2 = new decimal_js_1.default(interval[1]);
|
|
362
|
+
const f1 = evaluatePoint(x1);
|
|
363
|
+
const f2 = evaluatePoint(x2);
|
|
364
|
+
// Check if root is at subdivision point
|
|
365
|
+
if (f1.abs().lessThan(tol)) {
|
|
366
|
+
// Avoid duplicates
|
|
367
|
+
if (roots.length === 0 ||
|
|
368
|
+
x1
|
|
369
|
+
.minus(roots[roots.length - 1])
|
|
370
|
+
.abs()
|
|
371
|
+
.greaterThan(tol.times(10))) {
|
|
372
|
+
addRoot(x1);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
// Check for sign change
|
|
376
|
+
if (f1.times(f2).lessThan(0)) {
|
|
377
|
+
try {
|
|
378
|
+
let calculation;
|
|
379
|
+
switch (this.method) {
|
|
380
|
+
case NEWTON_RAPHSON_METHOD: {
|
|
381
|
+
// Start at the center of the interval
|
|
382
|
+
const centerOfInterval = x2.minus(x1).div(2).plus(x1);
|
|
383
|
+
calculation = this.NewtonRaphson(centerOfInterval);
|
|
384
|
+
break;
|
|
385
|
+
}
|
|
386
|
+
case BRENT_METHOD: {
|
|
387
|
+
calculation = this.Brent(x1, x2);
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
default: {
|
|
391
|
+
calculation = this.Brent(x1, x2);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (calculation.converged) {
|
|
395
|
+
const root = calculation.root;
|
|
396
|
+
// Avoid duplicate roots (within tolerance)
|
|
397
|
+
let isDuplicate = false;
|
|
398
|
+
for (const existingRoot of roots) {
|
|
399
|
+
if (root.minus(existingRoot).abs().lessThan(tol.times(10))) {
|
|
400
|
+
isDuplicate = true;
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (!isDuplicate) {
|
|
405
|
+
addRoot(root);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
catch { }
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
catch { }
|
|
413
|
+
}
|
|
414
|
+
// Check the final endpoint separately so a root exactly on the upper bound is not missed.
|
|
415
|
+
// Like endpoints visited during the scan, it may be outside the function's real domain.
|
|
416
|
+
try {
|
|
417
|
+
const lastPoint = bVal;
|
|
418
|
+
const fLast = evaluatePoint(lastPoint);
|
|
419
|
+
if (fLast.abs().lessThan(tol)) {
|
|
420
|
+
if (roots.length === 0 ||
|
|
421
|
+
lastPoint
|
|
422
|
+
.minus(roots[roots.length - 1])
|
|
423
|
+
.abs()
|
|
424
|
+
.greaterThan(tol.times(10))) {
|
|
425
|
+
addRoot(lastPoint);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
catch { }
|
|
430
|
+
return roots.sort((a, b) => a.comparedTo(b)).map(x => Expression_1.Expression.create(x));
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
exports.FunctionSolver = FunctionSolver;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Expression } from '../../core/classes/expression/Expression';
|
|
2
|
+
/** Options for the finite-range multi-start search performed by {@link MultivariateSolver}. */
|
|
3
|
+
export interface MultivariateSolverOptions {
|
|
4
|
+
/** Lower bound for each variable (default: -10) */
|
|
5
|
+
lowerBound?: number;
|
|
6
|
+
/** Upper bound for each variable (default: 10) */
|
|
7
|
+
upperBound?: number;
|
|
8
|
+
/** Number of grid points per variable (default: 5) */
|
|
9
|
+
gridPoints?: number;
|
|
10
|
+
/** Maximum Newton-Raphson iterations per start (default: 100) */
|
|
11
|
+
maxIterations?: number;
|
|
12
|
+
/** Convergence tolerance (default: 1e-12) */
|
|
13
|
+
tolerance?: number;
|
|
14
|
+
/** Step size for numerical Jacobian (default: 1e-8) */
|
|
15
|
+
derivativeStep?: number;
|
|
16
|
+
/** Tolerance for deduplicating roots (default: 1e-8) */
|
|
17
|
+
deduplicationTolerance?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Searches numerically for isolated real solutions of a multivariate system.
|
|
21
|
+
*
|
|
22
|
+
* Each equation is interpreted as `equation = 0`. The solver starts
|
|
23
|
+
* Newton-Raphson at every point in a Cartesian grid, approximates the Jacobian
|
|
24
|
+
* with central differences, and merges nearby converged solutions.
|
|
25
|
+
*
|
|
26
|
+
* @remarks
|
|
27
|
+
* This is a finite-range heuristic rather than a completeness proof. The number
|
|
28
|
+
* of starts is `gridPoints` raised to the number of variables, so cost grows
|
|
29
|
+
* rapidly with dimension. Singular Jacobians, failed evaluations, and starts
|
|
30
|
+
* that do not converge are discarded. Calculations use the ambient
|
|
31
|
+
* `decimal.js` precision, and the supplied equation and variable arrays are
|
|
32
|
+
* retained by the solver.
|
|
33
|
+
*
|
|
34
|
+
* The numerical linear solve requires a square Jacobian in ordinary use; this
|
|
35
|
+
* class is intended for isolated solutions of systems with as many equations
|
|
36
|
+
* as variables.
|
|
37
|
+
*/
|
|
38
|
+
export declare class MultivariateSolver {
|
|
39
|
+
private dedupTol;
|
|
40
|
+
private equations;
|
|
41
|
+
private gridPoints;
|
|
42
|
+
private h;
|
|
43
|
+
private lowerBound;
|
|
44
|
+
private maxIterations;
|
|
45
|
+
private tolerance;
|
|
46
|
+
private upperBound;
|
|
47
|
+
private variables;
|
|
48
|
+
/**
|
|
49
|
+
* Creates a multi-start solver over the configured limits.
|
|
50
|
+
*
|
|
51
|
+
* @param equations - Expressions interpreted as equations equal to zero.
|
|
52
|
+
* @param variables - Ordered variables corresponding to solution coordinates.
|
|
53
|
+
* @param options - Grid, iteration, differentiation, and deduplication settings.
|
|
54
|
+
*/
|
|
55
|
+
constructor(equations: Expression[], variables: string[], options?: MultivariateSolverOptions);
|
|
56
|
+
/**
|
|
57
|
+
* Evaluate all equations at a point, returning a vector of Decimal values.
|
|
58
|
+
*/
|
|
59
|
+
private evaluateSystem;
|
|
60
|
+
/**
|
|
61
|
+
* Generate grid starting points.
|
|
62
|
+
*/
|
|
63
|
+
private generateStartingPoints;
|
|
64
|
+
/**
|
|
65
|
+
* Check if a root is a duplicate of an existing one.
|
|
66
|
+
*/
|
|
67
|
+
private isDuplicate;
|
|
68
|
+
/**
|
|
69
|
+
* Compute the Jacobian matrix numerically using central differences.
|
|
70
|
+
*/
|
|
71
|
+
private jacobian;
|
|
72
|
+
/**
|
|
73
|
+
* Run Newton-Raphson from a single starting point.
|
|
74
|
+
* Returns the converged root or null if it didn't converge.
|
|
75
|
+
*/
|
|
76
|
+
private newtonRaphson;
|
|
77
|
+
/**
|
|
78
|
+
* Searches for roots from every configured grid point.
|
|
79
|
+
*
|
|
80
|
+
* @returns Deduplicated solutions as maps keyed in `variables` order. An empty
|
|
81
|
+
* array means that no start converged; it does not prove that no root exists.
|
|
82
|
+
*/
|
|
83
|
+
roots(): Map<string, Expression>[];
|
|
84
|
+
}
|