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,153 @@
|
|
|
1
|
+
import { Expression } from '../../core/classes/expression/Expression';
|
|
2
|
+
import { SOLUTIONS_SET } from '../../core/classes/parser/constants';
|
|
3
|
+
import { ValuesSet } from '../../core/classes/valuesSet/ValuesSet';
|
|
4
|
+
import type { ParserEntity } from '../../core/types';
|
|
5
|
+
import type { Root } from './FunctionSolver';
|
|
6
|
+
/** Describes whether accepted solutions were produced by numerical strategies, symbolic strategies, or both. */
|
|
7
|
+
export type SolutionsType = 'numeric' | 'symbolic' | 'mixed' | undefined;
|
|
8
|
+
/** Describes whether the stored descriptors represent finite solutions, indexed families, or all values. */
|
|
9
|
+
export type SolutionForm = 'finite' | 'parametric' | 'all';
|
|
10
|
+
/**
|
|
11
|
+
* A finite set of solution descriptors with solver-specific metadata.
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* `SolutionSet` inherits the finite-set storage semantics of {@link ValuesSet}: accepted
|
|
15
|
+
* descriptors are unique by symbolic equality, insertion order has no mathematical meaning,
|
|
16
|
+
* and values exposed through {@link elements} are copies rather than mutable references into
|
|
17
|
+
* the set. A descriptor normally represents one solution, but a descriptor containing the
|
|
18
|
+
* reserved `_n` index represents a parameterized family where `_n` ranges over the integers.
|
|
19
|
+
* The special `all` descriptor represents every value of the solved variable. Consequently,
|
|
20
|
+
* {@link count} reports the number of stored descriptors, not the cardinality of the
|
|
21
|
+
* mathematical solution set.
|
|
22
|
+
*
|
|
23
|
+
* {@link solutionsType} records solver provenance: whether accepted descriptors came from
|
|
24
|
+
* numerical strategies, symbolic/exact strategies, or both. It is not inferred from the
|
|
25
|
+
* printed shape of a descriptor, so a symbolic strategy may produce a value such as `1`.
|
|
26
|
+
* The orthogonal {@link solutionForm} property is derived from representation and distinguishes
|
|
27
|
+
* finite results, `_n`-indexed parametric families, and the `all` result.
|
|
28
|
+
*
|
|
29
|
+
* The class narrows membership to {@link Expression} values and keeps rejected singular
|
|
30
|
+
* candidates and numerical root metadata alongside the accepted solutions.
|
|
31
|
+
*
|
|
32
|
+
* Excluded values are enforced solver state, not merely advisory metadata. Once a value is excluded,
|
|
33
|
+
* adding the same value does not reintroduce it; excluding an already accepted value removes
|
|
34
|
+
* it from the solution set. {@link copy} preserves accepted values, exclusions, raw roots,
|
|
35
|
+
* partial-result state, solution type, and the unresolved expression when one is present.
|
|
36
|
+
*/
|
|
37
|
+
export declare class SolutionSet extends ValuesSet {
|
|
38
|
+
private excluded;
|
|
39
|
+
private roots;
|
|
40
|
+
dataType: typeof SOLUTIONS_SET;
|
|
41
|
+
partial: boolean;
|
|
42
|
+
/** Solver provenance for the currently accepted descriptors. */
|
|
43
|
+
solutionsType: SolutionsType;
|
|
44
|
+
unsolved?: Expression;
|
|
45
|
+
constructor(values?: Iterable<Expression>);
|
|
46
|
+
/** Tests whether a value is specifically a solver `SolutionSet`. */
|
|
47
|
+
static isSolutionSet(obj: unknown): obj is SolutionSet;
|
|
48
|
+
/**
|
|
49
|
+
* Combines numerical/symbolic provenance without changing any other solver state.
|
|
50
|
+
*/
|
|
51
|
+
private mergeSolutionsType;
|
|
52
|
+
/**
|
|
53
|
+
* Verifies and admits one candidate, reporting whether it belongs to this result after
|
|
54
|
+
* verification. Keeping this decision inside the same path used by {@link addSolution}
|
|
55
|
+
* avoids mistaking a pre-existing equal descriptor for a newly verified source candidate.
|
|
56
|
+
*/
|
|
57
|
+
private verifyAndAddSolution;
|
|
58
|
+
/**
|
|
59
|
+
* Replaces a parser-indexed solution while preserving Expression-only membership and
|
|
60
|
+
* uniqueness.
|
|
61
|
+
*/
|
|
62
|
+
__set__(indices: number[], value: ParserEntity): void;
|
|
63
|
+
/**
|
|
64
|
+
* Adds an accepted solution unless it is already present or explicitly excluded.
|
|
65
|
+
*/
|
|
66
|
+
add(x: Expression): SolutionSet;
|
|
67
|
+
/**
|
|
68
|
+
* Adds accepted solutions while preserving uniqueness and exclusions.
|
|
69
|
+
* The iterable is validated before the set is changed, so invalid input cannot leave a
|
|
70
|
+
* partially updated result.
|
|
71
|
+
*/
|
|
72
|
+
addMany(x: Iterable<Expression>): SolutionSet;
|
|
73
|
+
/**
|
|
74
|
+
* Stores numerical root-refinement metadata independently of the caller's object.
|
|
75
|
+
*/
|
|
76
|
+
addRawRoot(root: Root): SolutionSet;
|
|
77
|
+
/**
|
|
78
|
+
* Verifies a candidate against the source expression before admitting it to the set.
|
|
79
|
+
*
|
|
80
|
+
* Parameterized candidates that cannot yet be closed numerically are preserved. Closed
|
|
81
|
+
* residuals must evaluate nearly to zero. Candidates that encounter exact division by
|
|
82
|
+
* zero are recorded as exclusions instead.
|
|
83
|
+
*/
|
|
84
|
+
addSolution(solution: Expression, forFunction: Expression, variable: string): this;
|
|
85
|
+
/**
|
|
86
|
+
* Verifies and adds every candidate in an array or another `SolutionSet`.
|
|
87
|
+
*
|
|
88
|
+
* When the source is a `SolutionSet`, its numerical/symbolic provenance is retained if
|
|
89
|
+
* at least one source descriptor survives verification. Context-specific metadata such as
|
|
90
|
+
* exclusions, raw roots, partial state, and unresolved expressions is not transferred;
|
|
91
|
+
* use {@link append} when the complete solver result should be merged without revalidation.
|
|
92
|
+
*/
|
|
93
|
+
addSolutions(arr: Expression[] | SolutionSet, forFunction: Expression, variable: string): this;
|
|
94
|
+
/**
|
|
95
|
+
* Appends another solution result while preserving set and solver metadata.
|
|
96
|
+
*
|
|
97
|
+
* @remarks
|
|
98
|
+
* Exclusions are merged before accepted values so an excluded candidate cannot be
|
|
99
|
+
* reintroduced. Raw numerical-root records are copied. `partial` is combined with logical
|
|
100
|
+
* OR and differing defined solution types become `mixed`. If this set has no `unsolved`
|
|
101
|
+
* expression, the appended set's unresolved expression is copied; when both sets already
|
|
102
|
+
* carry different unresolved expressions, the receiver's value is retained because the
|
|
103
|
+
* current data model can represent only one such expression.
|
|
104
|
+
*/
|
|
105
|
+
append(s: SolutionSet): SolutionSet;
|
|
106
|
+
/** Returns an independent Expression copy at the requested insertion-order index. */
|
|
107
|
+
at(i: number): Expression | undefined;
|
|
108
|
+
/**
|
|
109
|
+
* Removes accepted solutions and all solver state so the instance can be reused.
|
|
110
|
+
*/
|
|
111
|
+
clear(): this;
|
|
112
|
+
/** Returns an independent copy including exclusions and raw-root metadata. */
|
|
113
|
+
copy(): SolutionSet;
|
|
114
|
+
/**
|
|
115
|
+
* Visits or maps accepted solutions in insertion order.
|
|
116
|
+
*
|
|
117
|
+
* Returning an Expression replaces the current solution while preserving uniqueness and
|
|
118
|
+
* exclusions. Returning `void` leaves the current solution unchanged, which allows the
|
|
119
|
+
* same method to be used for straightforward inspection without a dummy `return e`.
|
|
120
|
+
*/
|
|
121
|
+
each(callback: (e: Expression, i?: string | number, j?: string | number) => Expression | void): this;
|
|
122
|
+
each(callback: (e: ParserEntity, i?: string | number, j?: string | number) => ParserEntity | void): this;
|
|
123
|
+
/** Returns deep-copied accepted solution descriptors in deterministic insertion order. */
|
|
124
|
+
get elements(): Expression[];
|
|
125
|
+
evaluate(): SolutionSet;
|
|
126
|
+
/**
|
|
127
|
+
* Adds exclusions and removes any matching values that were already accepted.
|
|
128
|
+
*/
|
|
129
|
+
exclude(set: SolutionSet | ValuesSet): SolutionSet;
|
|
130
|
+
expand(): SolutionSet;
|
|
131
|
+
/** Visits independent Expression copies without changing this solution set. */
|
|
132
|
+
forEach(callback: (e: Expression, index: number) => void): void;
|
|
133
|
+
/** Returns an independent copy of the currently excluded values. */
|
|
134
|
+
getExcluded(): ValuesSet;
|
|
135
|
+
/**
|
|
136
|
+
* Returns independent copies of the stored numerical root-refinement records.
|
|
137
|
+
*/
|
|
138
|
+
getRawRoots(): Root[];
|
|
139
|
+
/**
|
|
140
|
+
* Classifies the mathematical result represented by the stored descriptors.
|
|
141
|
+
*
|
|
142
|
+
* Arbitrary symbolic parameters do not make a result parametric in this sense. The
|
|
143
|
+
* `parametric` form is reserved for solver-generated families that contain `_n`, where
|
|
144
|
+
* `_n` represents an integer index. The special `all` descriptor takes precedence if
|
|
145
|
+
* present.
|
|
146
|
+
*/
|
|
147
|
+
get solutionForm(): SolutionForm;
|
|
148
|
+
/** Iterates over independent Expression copies of the accepted solutions. */
|
|
149
|
+
[Symbol.iterator](): Iterator<Expression>;
|
|
150
|
+
text(): string;
|
|
151
|
+
/** Returns deep-copied accepted solutions as a plain array. */
|
|
152
|
+
toArray(): Expression[];
|
|
153
|
+
}
|
|
@@ -0,0 +1,357 @@
|
|
|
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.SolutionSet = void 0;
|
|
7
|
+
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
8
|
+
const Expression_1 = require("../../core/classes/expression/Expression");
|
|
9
|
+
const constants_1 = require("../../core/classes/parser/constants");
|
|
10
|
+
const ValuesSet_1 = require("../../core/classes/valuesSet/ValuesSet");
|
|
11
|
+
const common_1 = require("../../core/common/common");
|
|
12
|
+
const errors_1 = require("../../core/errors");
|
|
13
|
+
/**
|
|
14
|
+
* A finite set of solution descriptors with solver-specific metadata.
|
|
15
|
+
*
|
|
16
|
+
* @remarks
|
|
17
|
+
* `SolutionSet` inherits the finite-set storage semantics of {@link ValuesSet}: accepted
|
|
18
|
+
* descriptors are unique by symbolic equality, insertion order has no mathematical meaning,
|
|
19
|
+
* and values exposed through {@link elements} are copies rather than mutable references into
|
|
20
|
+
* the set. A descriptor normally represents one solution, but a descriptor containing the
|
|
21
|
+
* reserved `_n` index represents a parameterized family where `_n` ranges over the integers.
|
|
22
|
+
* The special `all` descriptor represents every value of the solved variable. Consequently,
|
|
23
|
+
* {@link count} reports the number of stored descriptors, not the cardinality of the
|
|
24
|
+
* mathematical solution set.
|
|
25
|
+
*
|
|
26
|
+
* {@link solutionsType} records solver provenance: whether accepted descriptors came from
|
|
27
|
+
* numerical strategies, symbolic/exact strategies, or both. It is not inferred from the
|
|
28
|
+
* printed shape of a descriptor, so a symbolic strategy may produce a value such as `1`.
|
|
29
|
+
* The orthogonal {@link solutionForm} property is derived from representation and distinguishes
|
|
30
|
+
* finite results, `_n`-indexed parametric families, and the `all` result.
|
|
31
|
+
*
|
|
32
|
+
* The class narrows membership to {@link Expression} values and keeps rejected singular
|
|
33
|
+
* candidates and numerical root metadata alongside the accepted solutions.
|
|
34
|
+
*
|
|
35
|
+
* Excluded values are enforced solver state, not merely advisory metadata. Once a value is excluded,
|
|
36
|
+
* adding the same value does not reintroduce it; excluding an already accepted value removes
|
|
37
|
+
* it from the solution set. {@link copy} preserves accepted values, exclusions, raw roots,
|
|
38
|
+
* partial-result state, solution type, and the unresolved expression when one is present.
|
|
39
|
+
*/
|
|
40
|
+
class SolutionSet extends ValuesSet_1.ValuesSet {
|
|
41
|
+
excluded = new ValuesSet_1.ValuesSet();
|
|
42
|
+
roots = [];
|
|
43
|
+
dataType = constants_1.SOLUTIONS_SET;
|
|
44
|
+
partial = false;
|
|
45
|
+
/** Solver provenance for the currently accepted descriptors. */
|
|
46
|
+
solutionsType = undefined;
|
|
47
|
+
unsolved;
|
|
48
|
+
constructor(values) {
|
|
49
|
+
super();
|
|
50
|
+
if (values) {
|
|
51
|
+
for (const v of values) {
|
|
52
|
+
this.add(v);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Tests whether a value is specifically a solver `SolutionSet`. */
|
|
57
|
+
static isSolutionSet(obj) {
|
|
58
|
+
return (0, common_1.isNerdamerNativeType)(obj, constants_1.SOLUTIONS_SET);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Combines numerical/symbolic provenance without changing any other solver state.
|
|
62
|
+
*/
|
|
63
|
+
mergeSolutionsType(solutionsType) {
|
|
64
|
+
if (this.solutionsType === undefined) {
|
|
65
|
+
this.solutionsType = solutionsType;
|
|
66
|
+
}
|
|
67
|
+
else if (solutionsType !== undefined && this.solutionsType !== solutionsType) {
|
|
68
|
+
this.solutionsType = 'mixed';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Verifies and admits one candidate, reporting whether it belongs to this result after
|
|
73
|
+
* verification. Keeping this decision inside the same path used by {@link addSolution}
|
|
74
|
+
* avoids mistaking a pre-existing equal descriptor for a newly verified source candidate.
|
|
75
|
+
*/
|
|
76
|
+
verifyAndAddSolution(solution, forFunction, variable) {
|
|
77
|
+
let retval = false;
|
|
78
|
+
try {
|
|
79
|
+
const evaluated = forFunction
|
|
80
|
+
.evaluate({ [variable]: solution.evaluate() })
|
|
81
|
+
.expand();
|
|
82
|
+
const isClosed = evaluated.variables().length === 0;
|
|
83
|
+
// Preserve parameterized candidates that cannot yet be verified, but
|
|
84
|
+
// require every closed residual, including complex values, to be zero.
|
|
85
|
+
if ((isClosed && evaluated.isNearlyZero()) || !isClosed) {
|
|
86
|
+
this.add(solution);
|
|
87
|
+
retval = this.has(solution);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (e) {
|
|
91
|
+
if (e instanceof errors_1.DivisionByZeroError) {
|
|
92
|
+
this.excluded.add(solution);
|
|
93
|
+
this.delete(solution);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return retval;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Replaces a parser-indexed solution while preserving Expression-only membership and
|
|
100
|
+
* uniqueness.
|
|
101
|
+
*/
|
|
102
|
+
__set__(indices, value) {
|
|
103
|
+
if (!Expression_1.Expression.isExpression(value)) {
|
|
104
|
+
throw new errors_1.UnexpectedDataType((0, errors_1.message)('expressionExpected', { type: value.dataType }));
|
|
105
|
+
}
|
|
106
|
+
if (this.excluded.has(value)) {
|
|
107
|
+
const index = indices[0];
|
|
108
|
+
if (index < 0 || index >= this.count()) {
|
|
109
|
+
throw new RangeError(`Index ${index} out of bounds for ${this.dataType} of length ${this.count()}`);
|
|
110
|
+
}
|
|
111
|
+
const current = this.at(index);
|
|
112
|
+
if (current) {
|
|
113
|
+
this.delete(current);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
super.__set__(indices, value);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Adds an accepted solution unless it is already present or explicitly excluded.
|
|
122
|
+
*/
|
|
123
|
+
add(x) {
|
|
124
|
+
if (!Expression_1.Expression.isExpression(x)) {
|
|
125
|
+
const entity = x;
|
|
126
|
+
throw new errors_1.UnexpectedDataType((0, errors_1.message)('expressionExpected', { type: entity.dataType }));
|
|
127
|
+
}
|
|
128
|
+
if (!this.excluded.has(x)) {
|
|
129
|
+
super.add(x);
|
|
130
|
+
}
|
|
131
|
+
return this;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Adds accepted solutions while preserving uniqueness and exclusions.
|
|
135
|
+
* The iterable is validated before the set is changed, so invalid input cannot leave a
|
|
136
|
+
* partially updated result.
|
|
137
|
+
*/
|
|
138
|
+
addMany(x) {
|
|
139
|
+
const values = [...x];
|
|
140
|
+
for (const value of values) {
|
|
141
|
+
if (!Expression_1.Expression.isExpression(value)) {
|
|
142
|
+
const entity = value;
|
|
143
|
+
throw new errors_1.UnexpectedDataType((0, errors_1.message)('expressionExpected', { type: entity.dataType }));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
for (const value of values) {
|
|
147
|
+
this.add(value);
|
|
148
|
+
}
|
|
149
|
+
return this;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Stores numerical root-refinement metadata independently of the caller's object.
|
|
153
|
+
*/
|
|
154
|
+
addRawRoot(root) {
|
|
155
|
+
this.roots.push({
|
|
156
|
+
root: new decimal_js_1.default(root.root),
|
|
157
|
+
iterations: root.iterations,
|
|
158
|
+
converged: root.converged,
|
|
159
|
+
error: new decimal_js_1.default(root.error),
|
|
160
|
+
errorMsg: root.errorMsg,
|
|
161
|
+
});
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Verifies a candidate against the source expression before admitting it to the set.
|
|
166
|
+
*
|
|
167
|
+
* Parameterized candidates that cannot yet be closed numerically are preserved. Closed
|
|
168
|
+
* residuals must evaluate nearly to zero. Candidates that encounter exact division by
|
|
169
|
+
* zero are recorded as exclusions instead.
|
|
170
|
+
*/
|
|
171
|
+
addSolution(solution, forFunction, variable) {
|
|
172
|
+
this.verifyAndAddSolution(solution, forFunction, variable);
|
|
173
|
+
return this;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Verifies and adds every candidate in an array or another `SolutionSet`.
|
|
177
|
+
*
|
|
178
|
+
* When the source is a `SolutionSet`, its numerical/symbolic provenance is retained if
|
|
179
|
+
* at least one source descriptor survives verification. Context-specific metadata such as
|
|
180
|
+
* exclusions, raw roots, partial state, and unresolved expressions is not transferred;
|
|
181
|
+
* use {@link append} when the complete solver result should be merged without revalidation.
|
|
182
|
+
*/
|
|
183
|
+
addSolutions(arr, forFunction, variable) {
|
|
184
|
+
let source;
|
|
185
|
+
let solutions;
|
|
186
|
+
if (SolutionSet.isSolutionSet(arr)) {
|
|
187
|
+
source = arr;
|
|
188
|
+
solutions = arr.elements;
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
solutions = arr;
|
|
192
|
+
}
|
|
193
|
+
let sourceAccepted = false;
|
|
194
|
+
for (const sol of solutions) {
|
|
195
|
+
if (this.verifyAndAddSolution(sol, forFunction, variable)) {
|
|
196
|
+
sourceAccepted = true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (source && sourceAccepted) {
|
|
200
|
+
this.mergeSolutionsType(source.solutionsType);
|
|
201
|
+
}
|
|
202
|
+
return this;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Appends another solution result while preserving set and solver metadata.
|
|
206
|
+
*
|
|
207
|
+
* @remarks
|
|
208
|
+
* Exclusions are merged before accepted values so an excluded candidate cannot be
|
|
209
|
+
* reintroduced. Raw numerical-root records are copied. `partial` is combined with logical
|
|
210
|
+
* OR and differing defined solution types become `mixed`. If this set has no `unsolved`
|
|
211
|
+
* expression, the appended set's unresolved expression is copied; when both sets already
|
|
212
|
+
* carry different unresolved expressions, the receiver's value is retained because the
|
|
213
|
+
* current data model can represent only one such expression.
|
|
214
|
+
*/
|
|
215
|
+
append(s) {
|
|
216
|
+
this.exclude(s.getExcluded());
|
|
217
|
+
this.addMany(s.elements);
|
|
218
|
+
for (const root of s.getRawRoots()) {
|
|
219
|
+
this.addRawRoot(root);
|
|
220
|
+
}
|
|
221
|
+
this.partial = this.partial || s.partial;
|
|
222
|
+
this.mergeSolutionsType(s.solutionsType);
|
|
223
|
+
if (!this.unsolved && s.unsolved) {
|
|
224
|
+
this.unsolved = s.unsolved.copy();
|
|
225
|
+
}
|
|
226
|
+
return this;
|
|
227
|
+
}
|
|
228
|
+
/** Returns an independent Expression copy at the requested insertion-order index. */
|
|
229
|
+
at(i) {
|
|
230
|
+
return super.at(i);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Removes accepted solutions and all solver state so the instance can be reused.
|
|
234
|
+
*/
|
|
235
|
+
clear() {
|
|
236
|
+
super.clear();
|
|
237
|
+
this.excluded.clear();
|
|
238
|
+
this.roots.length = 0;
|
|
239
|
+
this.partial = false;
|
|
240
|
+
this.solutionsType = undefined;
|
|
241
|
+
this.unsolved = undefined;
|
|
242
|
+
return this;
|
|
243
|
+
}
|
|
244
|
+
/** Returns an independent copy including exclusions and raw-root metadata. */
|
|
245
|
+
copy() {
|
|
246
|
+
const copy = new SolutionSet(this.elements);
|
|
247
|
+
copy.excluded = this.excluded.copy();
|
|
248
|
+
copy.roots = this.getRawRoots();
|
|
249
|
+
copy.solutionsType = this.solutionsType;
|
|
250
|
+
copy.partial = this.partial;
|
|
251
|
+
if (this.unsolved) {
|
|
252
|
+
copy.unsolved = this.unsolved.copy();
|
|
253
|
+
}
|
|
254
|
+
return copy;
|
|
255
|
+
}
|
|
256
|
+
each(callback) {
|
|
257
|
+
super.each((e, i, j) => {
|
|
258
|
+
if (!Expression_1.Expression.isExpression(e)) {
|
|
259
|
+
throw new errors_1.UnexpectedDataType((0, errors_1.message)('expressionExpected', { type: e.dataType }));
|
|
260
|
+
}
|
|
261
|
+
const mapped = callback(e, i, j);
|
|
262
|
+
if (mapped === undefined) {
|
|
263
|
+
return e;
|
|
264
|
+
}
|
|
265
|
+
if (!Expression_1.Expression.isExpression(mapped)) {
|
|
266
|
+
throw new errors_1.UnexpectedDataType((0, errors_1.message)('expressionExpected', { type: mapped.dataType }));
|
|
267
|
+
}
|
|
268
|
+
return mapped;
|
|
269
|
+
});
|
|
270
|
+
for (const value of this.excluded.elements) {
|
|
271
|
+
this.delete(value);
|
|
272
|
+
}
|
|
273
|
+
return this;
|
|
274
|
+
}
|
|
275
|
+
/** Returns deep-copied accepted solution descriptors in deterministic insertion order. */
|
|
276
|
+
get elements() {
|
|
277
|
+
return super.elements;
|
|
278
|
+
}
|
|
279
|
+
evaluate() {
|
|
280
|
+
return this.copy().each(e => e.evaluate());
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Adds exclusions and removes any matching values that were already accepted.
|
|
284
|
+
*/
|
|
285
|
+
exclude(set) {
|
|
286
|
+
const values = set.elements;
|
|
287
|
+
for (const value of values) {
|
|
288
|
+
if (!Expression_1.Expression.isExpression(value)) {
|
|
289
|
+
throw new errors_1.UnexpectedDataType((0, errors_1.message)('expressionExpected', { type: value.dataType }));
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
for (const value of values) {
|
|
293
|
+
this.excluded.add(value);
|
|
294
|
+
this.delete(value);
|
|
295
|
+
}
|
|
296
|
+
return this;
|
|
297
|
+
}
|
|
298
|
+
expand() {
|
|
299
|
+
return this.copy().each(e => e.expand());
|
|
300
|
+
}
|
|
301
|
+
/** Visits independent Expression copies without changing this solution set. */
|
|
302
|
+
forEach(callback) {
|
|
303
|
+
const values = this.elements;
|
|
304
|
+
for (let i = 0; i < values.length; i++) {
|
|
305
|
+
callback(values[i], i);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/** Returns an independent copy of the currently excluded values. */
|
|
309
|
+
getExcluded() {
|
|
310
|
+
return this.excluded.copy();
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Returns independent copies of the stored numerical root-refinement records.
|
|
314
|
+
*/
|
|
315
|
+
getRawRoots() {
|
|
316
|
+
return this.roots.map(root => ({
|
|
317
|
+
root: new decimal_js_1.default(root.root),
|
|
318
|
+
iterations: root.iterations,
|
|
319
|
+
converged: root.converged,
|
|
320
|
+
error: new decimal_js_1.default(root.error),
|
|
321
|
+
errorMsg: root.errorMsg,
|
|
322
|
+
}));
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Classifies the mathematical result represented by the stored descriptors.
|
|
326
|
+
*
|
|
327
|
+
* Arbitrary symbolic parameters do not make a result parametric in this sense. The
|
|
328
|
+
* `parametric` form is reserved for solver-generated families that contain `_n`, where
|
|
329
|
+
* `_n` represents an integer index. The special `all` descriptor takes precedence if
|
|
330
|
+
* present.
|
|
331
|
+
*/
|
|
332
|
+
get solutionForm() {
|
|
333
|
+
let retval = 'finite';
|
|
334
|
+
for (const solution of this.elements) {
|
|
335
|
+
if (solution.eq(constants_1.ALL_SYMBOL)) {
|
|
336
|
+
retval = 'all';
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
if (solution.hasVariable(constants_1.INDEX_VARIABLE)) {
|
|
340
|
+
retval = 'parametric';
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return retval;
|
|
344
|
+
}
|
|
345
|
+
/** Iterates over independent Expression copies of the accepted solutions. */
|
|
346
|
+
[Symbol.iterator]() {
|
|
347
|
+
return this.elements[Symbol.iterator]();
|
|
348
|
+
}
|
|
349
|
+
text() {
|
|
350
|
+
return super.text();
|
|
351
|
+
}
|
|
352
|
+
/** Returns deep-copied accepted solutions as a plain array. */
|
|
353
|
+
toArray() {
|
|
354
|
+
return this.elements;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
exports.SolutionSet = SolutionSet;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Expression } from '../../core/classes/expression/Expression';
|
|
2
|
+
import type { ExpressionInput } from '../../core/types';
|
|
3
|
+
import type Decimal from 'decimal.js';
|
|
4
|
+
export declare class Solver {
|
|
5
|
+
epsilon: number;
|
|
6
|
+
newtonEpsilon: number;
|
|
7
|
+
newtonMaxIterations: number;
|
|
8
|
+
newtonMaxSymbolicIterations: number;
|
|
9
|
+
rootsPerSide: number;
|
|
10
|
+
searchRadius: number;
|
|
11
|
+
symbolicEpsilon: number;
|
|
12
|
+
getPoints(f: (x: number) => number, start?: number, step?: number): number[];
|
|
13
|
+
newton(f: (x: number) => number, point: number): number | undefined;
|
|
14
|
+
newtonSymbolic(f: Expression, p: Expression, variable: string): Decimal | undefined;
|
|
15
|
+
solve(f: ExpressionInput): number[];
|
|
16
|
+
solveSymbolic(f: ExpressionInput): Decimal[];
|
|
17
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Solver = void 0;
|
|
4
|
+
const diff_1 = require("../../calculus/derivative/diff");
|
|
5
|
+
const Expression_1 = require("../../core/classes/expression/Expression");
|
|
6
|
+
const numeric_1 = require("../../core/functions/numeric");
|
|
7
|
+
class Solver {
|
|
8
|
+
// The numeric epsilon to be used
|
|
9
|
+
epsilon = 1e-13;
|
|
10
|
+
// The epsilon to be used when solving newton
|
|
11
|
+
newtonEpsilon = Number.EPSILON * 2;
|
|
12
|
+
// The maximum number of iteration for newton
|
|
13
|
+
newtonMaxIterations = 200;
|
|
14
|
+
newtonMaxSymbolicIterations = 50;
|
|
15
|
+
// The maximum roots to search for at each side
|
|
16
|
+
rootsPerSide = 10;
|
|
17
|
+
// The extend to which roots will be searched for
|
|
18
|
+
searchRadius = 100;
|
|
19
|
+
// const f = (x) => { return x ** 3 + 2 * x ** 2 - 1 }; // Gives false positives
|
|
20
|
+
symbolicEpsilon = 1e-16;
|
|
21
|
+
getPoints(f, start = 0, step = 1) {
|
|
22
|
+
const points = [];
|
|
23
|
+
// Roots found. This should be reset for each side
|
|
24
|
+
let roots = 0;
|
|
25
|
+
const testAndAdd = (point) => {
|
|
26
|
+
// Test if it's zero at that point
|
|
27
|
+
if (f(point) === 0 || Math.sign(f(point - step)) !== Math.sign(f(point + step))) {
|
|
28
|
+
points.push(point);
|
|
29
|
+
roots++;
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
};
|
|
34
|
+
const leftEnd = start - this.searchRadius;
|
|
35
|
+
const rightEnd = start + this.searchRadius;
|
|
36
|
+
// Test the right side
|
|
37
|
+
let n = start;
|
|
38
|
+
while (n < rightEnd) {
|
|
39
|
+
testAndAdd(n);
|
|
40
|
+
if (roots === this.rootsPerSide) {
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
n += step;
|
|
44
|
+
}
|
|
45
|
+
// Test the left side
|
|
46
|
+
n = start;
|
|
47
|
+
roots = 0;
|
|
48
|
+
while (n > leftEnd) {
|
|
49
|
+
testAndAdd(n);
|
|
50
|
+
if (roots === this.rootsPerSide) {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
n -= step;
|
|
54
|
+
}
|
|
55
|
+
return points;
|
|
56
|
+
}
|
|
57
|
+
newton(f, point) {
|
|
58
|
+
let iters = 0;
|
|
59
|
+
let x0 = point;
|
|
60
|
+
const fp = (0, numeric_1.diff)(f);
|
|
61
|
+
let x;
|
|
62
|
+
let e;
|
|
63
|
+
do {
|
|
64
|
+
const fx0 = f(x0); //store the result of the function
|
|
65
|
+
//if the value is zero then we're done because 0 - (0/d f(x0)) = 0
|
|
66
|
+
if (x0 === 0 && fx0 === 0) {
|
|
67
|
+
x = 0;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
iters++;
|
|
71
|
+
if (iters > this.newtonMaxIterations) {
|
|
72
|
+
return;
|
|
73
|
+
} //maximum iterations reached
|
|
74
|
+
x = x0 - fx0 / fp(x0);
|
|
75
|
+
e = Math.abs(x - x0);
|
|
76
|
+
x0 = x;
|
|
77
|
+
} while (e > this.newtonEpsilon);
|
|
78
|
+
//check if the number is indeed zero. 1e-13 seems to give the most accurate results
|
|
79
|
+
if (Math.abs(f(x)) <= this.epsilon) {
|
|
80
|
+
return x;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
newtonSymbolic(f, p, variable) {
|
|
84
|
+
let iters = 0;
|
|
85
|
+
let x0 = p.getMultiplier().toDecimal();
|
|
86
|
+
const fp = (0, diff_1.diff)(f, variable);
|
|
87
|
+
const values = { [variable]: p };
|
|
88
|
+
let x;
|
|
89
|
+
let e;
|
|
90
|
+
do {
|
|
91
|
+
const fx0 = f.evaluate(values);
|
|
92
|
+
if (iters++ > this.newtonMaxSymbolicIterations) {
|
|
93
|
+
return;
|
|
94
|
+
} //maximum iterations reached
|
|
95
|
+
x = x0.minus(fx0.div(fp.evaluate(values)).text({ decimal: true }));
|
|
96
|
+
// tracker = tracker.minus(fx0S.div(Expression.create(fp, values)))
|
|
97
|
+
e = x.minus(x0).abs();
|
|
98
|
+
x0 = x;
|
|
99
|
+
values[variable] = x0.isFinite() ? Expression_1.Expression.Number(x0) : x0.toString();
|
|
100
|
+
} while (e.abs().gte(this.symbolicEpsilon));
|
|
101
|
+
// console.log(tracker.toString())
|
|
102
|
+
return x;
|
|
103
|
+
}
|
|
104
|
+
solve(f) {
|
|
105
|
+
f = Expression_1.Expression.create(f);
|
|
106
|
+
const g = f.buildFunction();
|
|
107
|
+
const points = this.getPoints(g);
|
|
108
|
+
const solutions = [];
|
|
109
|
+
for (const p of points) {
|
|
110
|
+
const solution = this.newton(g, p);
|
|
111
|
+
if (solution !== undefined) {
|
|
112
|
+
solutions.push(solution);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return [...new Set(solutions)];
|
|
116
|
+
}
|
|
117
|
+
solveSymbolic(f) {
|
|
118
|
+
f = Expression_1.Expression.create(f);
|
|
119
|
+
const g = f.buildFunction();
|
|
120
|
+
const points = this.getPoints(g);
|
|
121
|
+
const variable = f.variables()[0];
|
|
122
|
+
const solutions = {};
|
|
123
|
+
for (const p of points) {
|
|
124
|
+
const solution = this.newtonSymbolic(f, Expression_1.Expression.Number(p), variable);
|
|
125
|
+
if (solution !== undefined) {
|
|
126
|
+
solutions[solution.toString()] = solution;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return Object.values(solutions);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.Solver = Solver;
|