mathjs 11.3.3 → 11.5.0
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/HISTORY.md +25 -0
- package/lib/browser/math.js +1 -1
- package/lib/browser/math.js.LICENSE.txt +2 -2
- package/lib/browser/math.js.map +1 -1
- package/lib/cjs/entry/dependenciesAny/dependenciesLyap.generated.js +26 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesPolynomialRoot.generated.js +42 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesSchur.generated.js +30 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesSylvester.generated.js +46 -0
- package/lib/cjs/entry/dependenciesAny.generated.js +28 -0
- package/lib/cjs/entry/impureFunctionsAny.generated.js +21 -17
- package/lib/cjs/entry/pureFunctionsAny.generated.js +100 -48
- package/lib/cjs/expression/embeddedDocs/embeddedDocs.js +8 -0
- package/lib/cjs/expression/embeddedDocs/function/algebra/polynomialRoot.js +15 -0
- package/lib/cjs/expression/embeddedDocs/function/matrix/lyap.js +15 -0
- package/lib/cjs/expression/embeddedDocs/function/matrix/reshape.js +1 -1
- package/lib/cjs/expression/embeddedDocs/function/matrix/schur.js +15 -0
- package/lib/cjs/expression/embeddedDocs/function/matrix/sylvester.js +15 -0
- package/lib/cjs/factoriesAny.js +28 -0
- package/lib/cjs/function/algebra/decomposition/schur.js +75 -0
- package/lib/cjs/function/algebra/lyap.js +57 -0
- package/lib/cjs/function/algebra/polynomialRoot.js +139 -0
- package/lib/cjs/function/algebra/simplify/wildcards.js +38 -0
- package/lib/cjs/function/algebra/simplify.js +161 -48
- package/lib/cjs/function/algebra/simplifyConstant.js +29 -12
- package/lib/cjs/function/algebra/sylvester.js +127 -0
- package/lib/cjs/function/matrix/forEach.js +1 -1
- package/lib/cjs/function/matrix/reshape.js +1 -1
- package/lib/cjs/function/string/format.js +24 -24
- package/lib/cjs/header.js +2 -2
- package/lib/cjs/version.js +1 -1
- package/lib/esm/entry/dependenciesAny/dependenciesLyap.generated.js +18 -0
- package/lib/esm/entry/dependenciesAny/dependenciesPolynomialRoot.generated.js +34 -0
- package/lib/esm/entry/dependenciesAny/dependenciesSchur.generated.js +22 -0
- package/lib/esm/entry/dependenciesAny/dependenciesSylvester.generated.js +38 -0
- package/lib/esm/entry/dependenciesAny.generated.js +4 -0
- package/lib/esm/entry/impureFunctionsAny.generated.js +22 -18
- package/lib/esm/entry/pureFunctionsAny.generated.js +87 -39
- package/lib/esm/expression/embeddedDocs/embeddedDocs.js +8 -0
- package/lib/esm/expression/embeddedDocs/function/algebra/polynomialRoot.js +8 -0
- package/lib/esm/expression/embeddedDocs/function/matrix/lyap.js +8 -0
- package/lib/esm/expression/embeddedDocs/function/matrix/reshape.js +1 -1
- package/lib/esm/expression/embeddedDocs/function/matrix/schur.js +8 -0
- package/lib/esm/expression/embeddedDocs/function/matrix/sylvester.js +8 -0
- package/lib/esm/factoriesAny.js +4 -0
- package/lib/esm/function/algebra/decomposition/schur.js +70 -0
- package/lib/esm/function/algebra/lyap.js +52 -0
- package/lib/esm/function/algebra/polynomialRoot.js +122 -0
- package/lib/esm/function/algebra/simplify/wildcards.js +20 -0
- package/lib/esm/function/algebra/simplify.js +162 -49
- package/lib/esm/function/algebra/simplifyConstant.js +29 -12
- package/lib/esm/function/algebra/sylvester.js +118 -0
- package/lib/esm/function/matrix/forEach.js +1 -1
- package/lib/esm/function/matrix/reshape.js +1 -1
- package/lib/esm/function/string/format.js +24 -24
- package/lib/esm/version.js +1 -1
- package/package.json +14 -14
- package/types/index.d.ts +88 -6
@@ -0,0 +1,122 @@
|
|
1
|
+
import { factory } from '../../utils/factory.js';
|
2
|
+
var name = 'polynomialRoot';
|
3
|
+
var dependencies = ['typed', 'isZero', 'equalScalar', 'add', 'subtract', 'multiply', 'divide', 'sqrt', 'unaryMinus', 'cbrt', 'typeOf', 'im', 're'];
|
4
|
+
export var createPolynomialRoot = /* #__PURE__ */factory(name, dependencies, _ref => {
|
5
|
+
var {
|
6
|
+
typed,
|
7
|
+
isZero,
|
8
|
+
equalScalar,
|
9
|
+
add,
|
10
|
+
subtract,
|
11
|
+
multiply,
|
12
|
+
divide,
|
13
|
+
sqrt,
|
14
|
+
unaryMinus,
|
15
|
+
cbrt,
|
16
|
+
typeOf,
|
17
|
+
im,
|
18
|
+
re
|
19
|
+
} = _ref;
|
20
|
+
/**
|
21
|
+
* Finds the numerical values of the distinct roots of a polynomial with real or complex coefficients.
|
22
|
+
* Currently operates only on linear, quadratic, and cubic polynomials using the standard
|
23
|
+
* formulas for the roots.
|
24
|
+
*
|
25
|
+
* Syntax:
|
26
|
+
*
|
27
|
+
* polynomialRoot(constant, linearCoeff, quadraticCoeff, cubicCoeff)
|
28
|
+
*
|
29
|
+
* Examples:
|
30
|
+
* // linear
|
31
|
+
* math.polynomialRoot(6, 3) // [-2]
|
32
|
+
* math.polynomialRoot(math.complex(6,3), 3) // [-2 - i]
|
33
|
+
* math.polynomialRoot(math.complex(6,3), math.complex(2,1)) // [-3 + 0i]
|
34
|
+
* // quadratic
|
35
|
+
* math.polynomialRoot(2, -3, 1) // [2, 1]
|
36
|
+
* math.polynomialRoot(8, 8, 2) // [-2]
|
37
|
+
* math.polynomialRoot(-2, 0, 1) // [1.4142135623730951, -1.4142135623730951]
|
38
|
+
* math.polynomialRoot(2, -2, 1) // [1 + i, 1 - i]
|
39
|
+
* math.polynomialRoot(math.complex(1,3), math.complex(-3, -2), 1) // [2 + i, 1 + i]
|
40
|
+
* // cubic
|
41
|
+
* math.polynomialRoot(-6, 11, -6, 1) // [1, 3, 2]
|
42
|
+
* math.polynomialRoot(-8, 0, 0, 1) // [-1 - 1.7320508075688774i, 2, -1 + 1.7320508075688774i]
|
43
|
+
* math.polynomialRoot(0, 8, 8, 2) // [0, -2]
|
44
|
+
* math.polynomialRoot(1, 1, 1, 1) // [-1 + 0i, 0 - i, 0 + i]
|
45
|
+
*
|
46
|
+
* See also:
|
47
|
+
* cbrt, sqrt
|
48
|
+
*
|
49
|
+
* @param {... number | Complex} coeffs
|
50
|
+
* The coefficients of the polynomial, starting with with the constant coefficent, followed
|
51
|
+
* by the linear coefficient and subsequent coefficients of increasing powers.
|
52
|
+
* @return {Array} The distinct roots of the polynomial
|
53
|
+
*/
|
54
|
+
|
55
|
+
return typed(name, {
|
56
|
+
'number|Complex, ...number|Complex': (constant, restCoeffs) => {
|
57
|
+
var coeffs = [constant, ...restCoeffs];
|
58
|
+
while (coeffs.length > 0 && isZero(coeffs[coeffs.length - 1])) {
|
59
|
+
coeffs.pop();
|
60
|
+
}
|
61
|
+
if (coeffs.length < 2) {
|
62
|
+
throw new RangeError("Polynomial [".concat(constant, ", ").concat(restCoeffs, "] must have a non-zero non-constant coefficient"));
|
63
|
+
}
|
64
|
+
switch (coeffs.length) {
|
65
|
+
case 2:
|
66
|
+
// linear
|
67
|
+
return [unaryMinus(divide(coeffs[0], coeffs[1]))];
|
68
|
+
case 3:
|
69
|
+
{
|
70
|
+
// quadratic
|
71
|
+
var [c, b, a] = coeffs;
|
72
|
+
var denom = multiply(2, a);
|
73
|
+
var d1 = multiply(b, b);
|
74
|
+
var d2 = multiply(4, a, c);
|
75
|
+
if (equalScalar(d1, d2)) return [divide(unaryMinus(b), denom)];
|
76
|
+
var discriminant = sqrt(subtract(d1, d2));
|
77
|
+
return [divide(subtract(discriminant, b), denom), divide(subtract(unaryMinus(discriminant), b), denom)];
|
78
|
+
}
|
79
|
+
case 4:
|
80
|
+
{
|
81
|
+
// cubic, cf. https://en.wikipedia.org/wiki/Cubic_equation
|
82
|
+
var [d, _c, _b, _a] = coeffs;
|
83
|
+
var _denom = unaryMinus(multiply(3, _a));
|
84
|
+
var D0_1 = multiply(_b, _b);
|
85
|
+
var D0_2 = multiply(3, _a, _c);
|
86
|
+
var D1_1 = add(multiply(2, _b, _b, _b), multiply(27, _a, _a, d));
|
87
|
+
var D1_2 = multiply(9, _a, _b, _c);
|
88
|
+
if (equalScalar(D0_1, D0_2) && equalScalar(D1_1, D1_2)) {
|
89
|
+
return [divide(_b, _denom)];
|
90
|
+
}
|
91
|
+
var Delta0 = subtract(D0_1, D0_2);
|
92
|
+
var Delta1 = subtract(D1_1, D1_2);
|
93
|
+
var discriminant1 = add(multiply(18, _a, _b, _c, d), multiply(_b, _b, _c, _c));
|
94
|
+
var discriminant2 = add(multiply(4, _b, _b, _b, d), multiply(4, _a, _c, _c, _c), multiply(27, _a, _a, d, d));
|
95
|
+
if (equalScalar(discriminant1, discriminant2)) {
|
96
|
+
return [divide(subtract(multiply(4, _a, _b, _c), add(multiply(9, _a, _a, d), multiply(_b, _b, _b))), multiply(_a, Delta0)),
|
97
|
+
// simple root
|
98
|
+
divide(subtract(multiply(9, _a, d), multiply(_b, _c)), multiply(2, Delta0)) // double root
|
99
|
+
];
|
100
|
+
}
|
101
|
+
// OK, we have three distinct roots
|
102
|
+
var Ccubed;
|
103
|
+
if (equalScalar(D0_1, D0_2)) {
|
104
|
+
Ccubed = Delta1;
|
105
|
+
} else {
|
106
|
+
Ccubed = divide(add(Delta1, sqrt(subtract(multiply(Delta1, Delta1), multiply(4, Delta0, Delta0, Delta0)))), 2);
|
107
|
+
}
|
108
|
+
var allRoots = true;
|
109
|
+
var rawRoots = cbrt(Ccubed, allRoots).toArray().map(C => divide(add(_b, C, divide(Delta0, C)), _denom));
|
110
|
+
return rawRoots.map(r => {
|
111
|
+
if (typeOf(r) === 'Complex' && equalScalar(re(r), re(r) + im(r))) {
|
112
|
+
return re(r);
|
113
|
+
}
|
114
|
+
return r;
|
115
|
+
});
|
116
|
+
}
|
117
|
+
default:
|
118
|
+
throw new RangeError("only implemented for cubic or lower-order polynomials, not ".concat(coeffs));
|
119
|
+
}
|
120
|
+
}
|
121
|
+
});
|
122
|
+
});
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { isConstantNode, isFunctionNode, isOperatorNode, isParenthesisNode } from '../../../utils/is.js';
|
2
|
+
export { isConstantNode, isSymbolNode as isVariableNode } from '../../../utils/is.js';
|
3
|
+
export function isNumericNode(x) {
|
4
|
+
return isConstantNode(x) || isOperatorNode(x) && x.isUnary() && isConstantNode(x.args[0]);
|
5
|
+
}
|
6
|
+
export function isConstantExpression(x) {
|
7
|
+
if (isConstantNode(x)) {
|
8
|
+
// Basic Constant types
|
9
|
+
return true;
|
10
|
+
}
|
11
|
+
if ((isFunctionNode(x) || isOperatorNode(x)) && x.args.every(isConstantExpression)) {
|
12
|
+
// Can be constant depending on arguments
|
13
|
+
return true;
|
14
|
+
}
|
15
|
+
if (isParenthesisNode(x) && isConstantExpression(x.content)) {
|
16
|
+
// Parenthesis are transparent
|
17
|
+
return true;
|
18
|
+
}
|
19
|
+
return false; // Probably missing some edge cases
|
20
|
+
}
|
@@ -1,4 +1,5 @@
|
|
1
|
-
import {
|
1
|
+
import { isParenthesisNode } from '../../utils/is.js';
|
2
|
+
import { isConstantNode, isVariableNode, isNumericNode, isConstantExpression } from './simplify/wildcards.js';
|
2
3
|
import { factory } from '../../utils/factory.js';
|
3
4
|
import { createUtil } from './simplify/util.js';
|
4
5
|
import { hasOwnProperty } from '../../utils/object.js';
|
@@ -75,9 +76,15 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
75
76
|
* expression is that variables starting with the following characters are
|
76
77
|
* interpreted as wildcards:
|
77
78
|
*
|
78
|
-
* - 'n' -
|
79
|
-
* - 'c' -
|
80
|
-
* - '
|
79
|
+
* - 'n' - Matches any node [Node]
|
80
|
+
* - 'c' - Matches a constant literal (5 or 3.2) [ConstantNode]
|
81
|
+
* - 'cl' - Matches a constant literal; same as c [ConstantNode]
|
82
|
+
* - 'cd' - Matches a decimal literal (5 or -3.2) [ConstantNode or unaryMinus wrapping a ConstantNode]
|
83
|
+
* - 'ce' - Matches a constant expression (-5 or √3) [Expressions consisting of only ConstantNodes, functions, and operators]
|
84
|
+
* - 'v' - Matches a variable; anything not matched by c (-5 or x) [Node that is not a ConstantNode]
|
85
|
+
* - 'vl' - Matches a variable literal (x or y) [SymbolNode]
|
86
|
+
* - 'vd' - Matches a non-decimal expression; anything not matched by cd (x or √3) [Node that is not a ConstantNode or unaryMinus that is wrapping a ConstantNode]
|
87
|
+
* - 've' - Matches a variable expression; anything not matched by ce (x or 2x) [Expressions that contain a SymbolNode or other non-constant term]
|
81
88
|
*
|
82
89
|
* The default list of rules is exposed on the function as `simplify.rules`
|
83
90
|
* and can be used as a basis to built a set of custom rules. Note that since
|
@@ -250,7 +257,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
250
257
|
}
|
251
258
|
}
|
252
259
|
}, {
|
253
|
-
s: '-(
|
260
|
+
s: '-(cl*v) -> v * (-cl)',
|
254
261
|
// make non-constant terms positive
|
255
262
|
assuming: {
|
256
263
|
multiply: {
|
@@ -261,7 +268,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
261
268
|
}
|
262
269
|
}
|
263
270
|
}, {
|
264
|
-
s: '-(
|
271
|
+
s: '-(cl*v) -> (-cl) * v',
|
265
272
|
// non-commutative version, part 1
|
266
273
|
assuming: {
|
267
274
|
multiply: {
|
@@ -272,7 +279,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
272
279
|
}
|
273
280
|
}
|
274
281
|
}, {
|
275
|
-
s: '-(v*
|
282
|
+
s: '-(v*cl) -> v * (-cl)',
|
276
283
|
// non-commutative version, part 2
|
277
284
|
assuming: {
|
278
285
|
multiply: {
|
@@ -330,24 +337,24 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
330
337
|
},
|
331
338
|
// collect like factors; into a sum, only do this for nonconstants
|
332
339
|
{
|
333
|
-
l: '
|
334
|
-
r: '
|
340
|
+
l: ' vd * ( vd * n1 + n2)',
|
341
|
+
r: 'vd^2 * n1 + vd * n2'
|
335
342
|
}, {
|
336
|
-
s: '
|
343
|
+
s: ' vd * (vd^n4 * n1 + n2) -> vd^(1+n4) * n1 + vd * n2',
|
337
344
|
assuming: {
|
338
345
|
divide: {
|
339
346
|
total: true
|
340
347
|
}
|
341
348
|
} // v*1/v = v^(1+-1) needs 1/v
|
342
349
|
}, {
|
343
|
-
s: '
|
350
|
+
s: 'vd^n3 * ( vd * n1 + n2) -> vd^(n3+1) * n1 + vd^n3 * n2',
|
344
351
|
assuming: {
|
345
352
|
divide: {
|
346
353
|
total: true
|
347
354
|
}
|
348
355
|
}
|
349
356
|
}, {
|
350
|
-
s: '
|
357
|
+
s: 'vd^n3 * (vd^n4 * n1 + n2) -> vd^(n3+n4) * n1 + vd^n3 * n2',
|
351
358
|
assuming: {
|
352
359
|
divide: {
|
353
360
|
total: true
|
@@ -390,8 +397,8 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
390
397
|
l: 'n+-n',
|
391
398
|
r: '0'
|
392
399
|
}, {
|
393
|
-
l: '
|
394
|
-
r: '
|
400
|
+
l: 'vd*n + vd',
|
401
|
+
r: 'vd*(n+1)'
|
395
402
|
},
|
396
403
|
// NOTE: leftmost position is special:
|
397
404
|
{
|
@@ -405,9 +412,17 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
405
412
|
}, {
|
406
413
|
l: 'n3^(-n4)*n1 + n3^n5 * n2',
|
407
414
|
r: 'n3^(-n4)*(n1 + n3^(n4+n5)*n2)'
|
415
|
+
},
|
416
|
+
// noncommutative additional cases (term collection & factoring)
|
417
|
+
{
|
418
|
+
s: 'n*vd + vd -> (n+1)*vd',
|
419
|
+
assuming: {
|
420
|
+
multiply: {
|
421
|
+
commutative: false
|
422
|
+
}
|
423
|
+
}
|
408
424
|
}, {
|
409
|
-
s: '
|
410
|
-
// noncommutative additional cases
|
425
|
+
s: 'vd + n*vd -> (1+n)*vd',
|
411
426
|
assuming: {
|
412
427
|
multiply: {
|
413
428
|
commutative: false
|
@@ -420,6 +435,16 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
420
435
|
commutative: false
|
421
436
|
}
|
422
437
|
}
|
438
|
+
}, {
|
439
|
+
s: 'n^n1 * n -> n^(n1+1)',
|
440
|
+
assuming: {
|
441
|
+
divide: {
|
442
|
+
total: true
|
443
|
+
},
|
444
|
+
multiply: {
|
445
|
+
commutative: false
|
446
|
+
}
|
447
|
+
}
|
423
448
|
}, {
|
424
449
|
s: 'n1*n3^(-n4) + n2 * n3 -> (n1 + n2*n3^(n4 + 1))*n3^(-n4)',
|
425
450
|
assuming: {
|
@@ -435,10 +460,17 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
435
460
|
}
|
436
461
|
}
|
437
462
|
}, {
|
438
|
-
l: 'n*
|
439
|
-
r: '(n+1)*
|
463
|
+
l: 'n*cd + cd',
|
464
|
+
r: '(n+1)*cd'
|
440
465
|
}, {
|
441
|
-
s: '
|
466
|
+
s: 'cd*n + cd -> cd*(n+1)',
|
467
|
+
assuming: {
|
468
|
+
multiply: {
|
469
|
+
commutative: false
|
470
|
+
}
|
471
|
+
}
|
472
|
+
}, {
|
473
|
+
s: 'cd + cd*n -> cd*(1+n)',
|
442
474
|
assuming: {
|
443
475
|
multiply: {
|
444
476
|
commutative: false
|
@@ -469,7 +501,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
469
501
|
},
|
470
502
|
// final ordering of constants
|
471
503
|
{
|
472
|
-
s: '
|
504
|
+
s: 'ce+ve -> ve+ce',
|
473
505
|
assuming: {
|
474
506
|
add: {
|
475
507
|
commutative: true
|
@@ -481,7 +513,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
481
513
|
}
|
482
514
|
}
|
483
515
|
}, {
|
484
|
-
s: '
|
516
|
+
s: 'vd*cd -> cd*vd',
|
485
517
|
assuming: {
|
486
518
|
multiply: {
|
487
519
|
commutative: true
|
@@ -599,15 +631,33 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
599
631
|
newRule.evaluate = parse(ruleObject.evaluate);
|
600
632
|
}
|
601
633
|
if (isAssociative(newRule.l, context)) {
|
634
|
+
var nonCommutative = !isCommutative(newRule.l, context);
|
635
|
+
var leftExpandsym;
|
636
|
+
// Gen. the LHS placeholder used in this NC-context specific expansion rules
|
637
|
+
if (nonCommutative) leftExpandsym = _getExpandPlaceholderSymbol();
|
602
638
|
var makeNode = createMakeNodeFunction(newRule.l);
|
603
639
|
var expandsym = _getExpandPlaceholderSymbol();
|
604
640
|
newRule.expanded = {};
|
605
|
-
newRule.expanded.l = makeNode([newRule.l
|
641
|
+
newRule.expanded.l = makeNode([newRule.l, expandsym]);
|
606
642
|
// Push the expandsym into the deepest possible branch.
|
607
643
|
// This helps to match the newRule against nodes returned from getSplits() later on.
|
608
644
|
flatten(newRule.expanded.l, context);
|
609
645
|
unflattenr(newRule.expanded.l, context);
|
610
646
|
newRule.expanded.r = makeNode([newRule.r, expandsym]);
|
647
|
+
|
648
|
+
// In and for a non-commutative context, attempting with yet additional expansion rules makes
|
649
|
+
// way for more matches cases of multi-arg expressions; such that associative rules (such as
|
650
|
+
// 'n*n -> n^2') can be applied to exprs. such as 'a * b * b' and 'a * b * b * a'.
|
651
|
+
if (nonCommutative) {
|
652
|
+
// 'Non-commutative' 1: LHS (placeholder) only
|
653
|
+
newRule.expandedNC1 = {};
|
654
|
+
newRule.expandedNC1.l = makeNode([leftExpandsym, newRule.l]);
|
655
|
+
newRule.expandedNC1.r = makeNode([leftExpandsym, newRule.r]);
|
656
|
+
// 'Non-commutative' 2: farmost LHS and RHS placeholders
|
657
|
+
newRule.expandedNC2 = {};
|
658
|
+
newRule.expandedNC2.l = makeNode([leftExpandsym, newRule.expanded.l]);
|
659
|
+
newRule.expandedNC2.r = makeNode([leftExpandsym, newRule.expanded.r]);
|
660
|
+
}
|
611
661
|
}
|
612
662
|
return newRule;
|
613
663
|
}
|
@@ -813,6 +863,16 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
813
863
|
repl = rule.expanded.r;
|
814
864
|
matches = _ruleMatch(rule.expanded.l, res, mergedContext)[0];
|
815
865
|
}
|
866
|
+
// Additional, non-commutative context expansion-rules
|
867
|
+
if (!matches && rule.expandedNC1) {
|
868
|
+
repl = rule.expandedNC1.r;
|
869
|
+
matches = _ruleMatch(rule.expandedNC1.l, res, mergedContext)[0];
|
870
|
+
if (!matches) {
|
871
|
+
// Existence of NC1 implies NC2
|
872
|
+
repl = rule.expandedNC2.r;
|
873
|
+
matches = _ruleMatch(rule.expandedNC2.l, res, mergedContext)[0];
|
874
|
+
}
|
875
|
+
}
|
816
876
|
if (matches) {
|
817
877
|
// const before = res.toString({parenthesis: 'all'})
|
818
878
|
|
@@ -1030,8 +1090,8 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
1030
1090
|
res = mergeChildMatches(childMatches);
|
1031
1091
|
} else if (node.args.length >= 2 && rule.args.length === 2) {
|
1032
1092
|
// node is flattened, rule is not
|
1033
|
-
// Associative operators/functions can be split in different ways so we check if the rule
|
1034
|
-
// them and return their union.
|
1093
|
+
// Associative operators/functions can be split in different ways so we check if the rule
|
1094
|
+
// matches for each of them and return their union.
|
1035
1095
|
var splits = getSplits(node, context);
|
1036
1096
|
var splitMatches = [];
|
1037
1097
|
for (var _i2 = 0; _i2 < splits.length; _i2++) {
|
@@ -1047,9 +1107,8 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
1047
1107
|
}
|
1048
1108
|
} else if (rule instanceof SymbolNode) {
|
1049
1109
|
// If the rule is a SymbolNode, then it carries a special meaning
|
1050
|
-
// according to the first
|
1051
|
-
//
|
1052
|
-
// n.* matches any node
|
1110
|
+
// according to the first one or two characters of the symbol node name.
|
1111
|
+
// These meanings are expalined in the documentation for simplify()
|
1053
1112
|
if (rule.name.length === 0) {
|
1054
1113
|
throw new Error('Symbol in rule has 0 length...!?');
|
1055
1114
|
}
|
@@ -1058,29 +1117,83 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
1058
1117
|
if (rule.name !== node.name) {
|
1059
1118
|
return [];
|
1060
1119
|
}
|
1061
|
-
} else if (rule.name[0] === 'n' || rule.name.substring(0, 2) === '_p') {
|
1062
|
-
// rule matches _anything_, so assign this node to the rule.name placeholder
|
1063
|
-
// Assign node to the rule.name placeholder.
|
1064
|
-
// Our parent will check for matches among placeholders.
|
1065
|
-
res[0].placeholders[rule.name] = node;
|
1066
|
-
} else if (rule.name[0] === 'v') {
|
1067
|
-
// rule matches any variable thing (not a ConstantNode)
|
1068
|
-
if (!isConstantNode(node)) {
|
1069
|
-
res[0].placeholders[rule.name] = node;
|
1070
|
-
} else {
|
1071
|
-
// Mis-match: rule was expecting something other than a ConstantNode
|
1072
|
-
return [];
|
1073
|
-
}
|
1074
|
-
} else if (rule.name[0] === 'c') {
|
1075
|
-
// rule matches any ConstantNode
|
1076
|
-
if (node instanceof ConstantNode) {
|
1077
|
-
res[0].placeholders[rule.name] = node;
|
1078
|
-
} else {
|
1079
|
-
// Mis-match: rule was expecting a ConstantNode
|
1080
|
-
return [];
|
1081
|
-
}
|
1082
1120
|
} else {
|
1083
|
-
|
1121
|
+
// wildcards are composed of up to two alphabetic or underscore characters
|
1122
|
+
switch (rule.name[1] >= 'a' && rule.name[1] <= 'z' ? rule.name.substring(0, 2) : rule.name[0]) {
|
1123
|
+
case 'n':
|
1124
|
+
case '_p':
|
1125
|
+
// rule matches _anything_, so assign this node to the rule.name placeholder
|
1126
|
+
// Assign node to the rule.name placeholder.
|
1127
|
+
// Our parent will check for matches among placeholders.
|
1128
|
+
res[0].placeholders[rule.name] = node;
|
1129
|
+
break;
|
1130
|
+
case 'c':
|
1131
|
+
case 'cl':
|
1132
|
+
// rule matches a ConstantNode
|
1133
|
+
if (isConstantNode(node)) {
|
1134
|
+
res[0].placeholders[rule.name] = node;
|
1135
|
+
} else {
|
1136
|
+
// mis-match: rule does not encompass current node
|
1137
|
+
return [];
|
1138
|
+
}
|
1139
|
+
break;
|
1140
|
+
case 'v':
|
1141
|
+
// rule matches anything other than a ConstantNode
|
1142
|
+
if (!isConstantNode(node)) {
|
1143
|
+
res[0].placeholders[rule.name] = node;
|
1144
|
+
} else {
|
1145
|
+
// mis-match: rule does not encompass current node
|
1146
|
+
return [];
|
1147
|
+
}
|
1148
|
+
break;
|
1149
|
+
case 'vl':
|
1150
|
+
// rule matches VariableNode
|
1151
|
+
if (isVariableNode(node)) {
|
1152
|
+
res[0].placeholders[rule.name] = node;
|
1153
|
+
} else {
|
1154
|
+
// mis-match: rule does not encompass current node
|
1155
|
+
return [];
|
1156
|
+
}
|
1157
|
+
break;
|
1158
|
+
case 'cd':
|
1159
|
+
// rule matches a ConstantNode or unaryMinus-wrapped ConstantNode
|
1160
|
+
if (isNumericNode(node)) {
|
1161
|
+
res[0].placeholders[rule.name] = node;
|
1162
|
+
} else {
|
1163
|
+
// mis-match: rule does not encompass current node
|
1164
|
+
return [];
|
1165
|
+
}
|
1166
|
+
break;
|
1167
|
+
case 'vd':
|
1168
|
+
// rule matches anything other than a ConstantNode or unaryMinus-wrapped ConstantNode
|
1169
|
+
if (!isNumericNode(node)) {
|
1170
|
+
res[0].placeholders[rule.name] = node;
|
1171
|
+
} else {
|
1172
|
+
// mis-match: rule does not encompass current node
|
1173
|
+
return [];
|
1174
|
+
}
|
1175
|
+
break;
|
1176
|
+
case 'ce':
|
1177
|
+
// rule matches expressions that have a constant value
|
1178
|
+
if (isConstantExpression(node)) {
|
1179
|
+
res[0].placeholders[rule.name] = node;
|
1180
|
+
} else {
|
1181
|
+
// mis-match: rule does not encompass current node
|
1182
|
+
return [];
|
1183
|
+
}
|
1184
|
+
break;
|
1185
|
+
case 've':
|
1186
|
+
// rule matches expressions that do not have a constant value
|
1187
|
+
if (!isConstantExpression(node)) {
|
1188
|
+
res[0].placeholders[rule.name] = node;
|
1189
|
+
} else {
|
1190
|
+
// mis-match: rule does not encompass current node
|
1191
|
+
return [];
|
1192
|
+
}
|
1193
|
+
break;
|
1194
|
+
default:
|
1195
|
+
throw new Error('Invalid symbol in rule: ' + rule.name);
|
1196
|
+
}
|
1084
1197
|
}
|
1085
1198
|
} else if (rule instanceof ConstantNode) {
|
1086
1199
|
// Literal constant must match exactly
|
@@ -286,20 +286,37 @@ export var createSimplifyConstant = /* #__PURE__ */factory(name, dependencies, _
|
|
286
286
|
* @return - Either a Node representing a binary expression or Fraction
|
287
287
|
*/
|
288
288
|
function foldOp(fn, args, makeNode, options) {
|
289
|
-
|
290
|
-
|
289
|
+
var first = args.shift();
|
290
|
+
|
291
|
+
// In the following reduction, sofar always has one of the three following
|
292
|
+
// forms: [NODE], [CONSTANT], or [NODE, CONSTANT]
|
293
|
+
var reduction = args.reduce((sofar, next) => {
|
294
|
+
if (!isNode(next)) {
|
295
|
+
var last = sofar.pop();
|
296
|
+
if (isNode(last)) {
|
297
|
+
return [last, next];
|
298
|
+
}
|
299
|
+
// Two constants in a row, try to fold them into one
|
291
300
|
try {
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
} else if (!isNode(b)) {
|
299
|
-
b = _toNode(b);
|
301
|
+
sofar.push(_eval(fn, [last, next], options));
|
302
|
+
return sofar;
|
303
|
+
} catch (ignoreandcontinue) {
|
304
|
+
sofar.push(last);
|
305
|
+
// fall through to Node case
|
306
|
+
}
|
300
307
|
}
|
301
|
-
|
302
|
-
|
308
|
+
|
309
|
+
// Encountered a Node, or failed folding --
|
310
|
+
// collapse everything so far into a single tree:
|
311
|
+
sofar.push(_ensureNode(sofar.pop()));
|
312
|
+
var newtree = sofar.length === 1 ? sofar[0] : makeNode(sofar);
|
313
|
+
return [makeNode([newtree, _ensureNode(next)])];
|
314
|
+
}, [first]);
|
315
|
+
if (reduction.length === 1) {
|
316
|
+
return reduction[0];
|
317
|
+
}
|
318
|
+
// Might end up with a tree and a constant at the end:
|
319
|
+
return makeNode([reduction[0], _toNode(reduction[1])]);
|
303
320
|
}
|
304
321
|
|
305
322
|
// destroys the original node and returns a folded one
|
@@ -0,0 +1,118 @@
|
|
1
|
+
import { factory } from '../../utils/factory.js';
|
2
|
+
var name = 'sylvester';
|
3
|
+
var dependencies = ['typed', 'schur', 'matrixFromColumns', 'matrix', 'multiply', 'range', 'concat', 'transpose', 'index', 'subset', 'add', 'subtract', 'identity', 'lusolve', 'abs'];
|
4
|
+
export var createSylvester = /* #__PURE__ */factory(name, dependencies, _ref => {
|
5
|
+
var {
|
6
|
+
typed,
|
7
|
+
schur,
|
8
|
+
matrixFromColumns,
|
9
|
+
matrix,
|
10
|
+
multiply,
|
11
|
+
range,
|
12
|
+
concat,
|
13
|
+
transpose,
|
14
|
+
index,
|
15
|
+
subset,
|
16
|
+
add,
|
17
|
+
subtract,
|
18
|
+
identity,
|
19
|
+
lusolve,
|
20
|
+
abs
|
21
|
+
} = _ref;
|
22
|
+
/**
|
23
|
+
*
|
24
|
+
* Solves the real-valued Sylvester equation AX+XB=C for X, where A, B and C are
|
25
|
+
* matrices of appropriate dimensions, being A and B squared. Notice that other
|
26
|
+
* equivalent definitions for the Sylvester equation exist and this function
|
27
|
+
* assumes the one presented in the original publication of the the Bartels-
|
28
|
+
* Stewart algorithm, which is implemented by this function.
|
29
|
+
* https://en.wikipedia.org/wiki/Sylvester_equation
|
30
|
+
*
|
31
|
+
* Syntax:
|
32
|
+
*
|
33
|
+
* math.sylvester(A, B, C)
|
34
|
+
*
|
35
|
+
* Examples:
|
36
|
+
*
|
37
|
+
* const A = [[-1, -2], [1, 1]]
|
38
|
+
* const B = [[2, -1], [1, -2]]
|
39
|
+
* const C = [[-3, 2], [3, 0]]
|
40
|
+
* math.sylvester(A, B, C) // returns DenseMatrix [[-0.25, 0.25], [1.5, -1.25]]
|
41
|
+
*
|
42
|
+
* See also:
|
43
|
+
*
|
44
|
+
* schur, lyap
|
45
|
+
*
|
46
|
+
* @param {Matrix | Array} A Matrix A
|
47
|
+
* @param {Matrix | Array} B Matrix B
|
48
|
+
* @param {Matrix | Array} C Matrix C
|
49
|
+
* @return {Matrix | Array} Matrix X, solving the Sylvester equation
|
50
|
+
*/
|
51
|
+
return typed(name, {
|
52
|
+
'Matrix, Matrix, Matrix': _sylvester,
|
53
|
+
'Array, Matrix, Matrix': function ArrayMatrixMatrix(A, B, C) {
|
54
|
+
return _sylvester(matrix(A), B, C);
|
55
|
+
},
|
56
|
+
'Array, Array, Matrix': function ArrayArrayMatrix(A, B, C) {
|
57
|
+
return _sylvester(matrix(A), matrix(B), C);
|
58
|
+
},
|
59
|
+
'Array, Matrix, Array': function ArrayMatrixArray(A, B, C) {
|
60
|
+
return _sylvester(matrix(A), B, matrix(C));
|
61
|
+
},
|
62
|
+
'Matrix, Array, Matrix': function MatrixArrayMatrix(A, B, C) {
|
63
|
+
return _sylvester(A, matrix(B), C);
|
64
|
+
},
|
65
|
+
'Matrix, Array, Array': function MatrixArrayArray(A, B, C) {
|
66
|
+
return _sylvester(A, matrix(B), matrix(C));
|
67
|
+
},
|
68
|
+
'Matrix, Matrix, Array': function MatrixMatrixArray(A, B, C) {
|
69
|
+
return _sylvester(A, B, matrix(C));
|
70
|
+
},
|
71
|
+
'Array, Array, Array': function ArrayArrayArray(A, B, C) {
|
72
|
+
return _sylvester(matrix(A), matrix(B), matrix(C)).toArray();
|
73
|
+
}
|
74
|
+
});
|
75
|
+
function _sylvester(A, B, C) {
|
76
|
+
var n = B.size()[0];
|
77
|
+
var m = A.size()[0];
|
78
|
+
var sA = schur(A);
|
79
|
+
var F = sA.T;
|
80
|
+
var U = sA.U;
|
81
|
+
var sB = schur(multiply(-1, B));
|
82
|
+
var G = sB.T;
|
83
|
+
var V = sB.U;
|
84
|
+
var D = multiply(multiply(transpose(U), C), V);
|
85
|
+
var all = range(0, m);
|
86
|
+
var y = [];
|
87
|
+
var hc = (a, b) => concat(a, b, 1);
|
88
|
+
var vc = (a, b) => concat(a, b, 0);
|
89
|
+
for (var k = 0; k < n; k++) {
|
90
|
+
if (k < n - 1 && abs(subset(G, index(k + 1, k))) > 1e-5) {
|
91
|
+
var RHS = vc(subset(D, index(all, k)), subset(D, index(all, k + 1)));
|
92
|
+
for (var j = 0; j < k; j++) {
|
93
|
+
RHS = add(RHS, vc(multiply(y[j], subset(G, index(j, k))), multiply(y[j], subset(G, index(j, k + 1)))));
|
94
|
+
}
|
95
|
+
var gkk = multiply(identity(m), multiply(-1, subset(G, index(k, k))));
|
96
|
+
var gmk = multiply(identity(m), multiply(-1, subset(G, index(k + 1, k))));
|
97
|
+
var gkm = multiply(identity(m), multiply(-1, subset(G, index(k, k + 1))));
|
98
|
+
var gmm = multiply(identity(m), multiply(-1, subset(G, index(k + 1, k + 1))));
|
99
|
+
var LHS = vc(hc(add(F, gkk), gmk), hc(gkm, add(F, gmm)));
|
100
|
+
var yAux = lusolve(LHS, RHS);
|
101
|
+
y[k] = yAux.subset(index(range(0, m), 0));
|
102
|
+
y[k + 1] = yAux.subset(index(range(m, 2 * m), 0));
|
103
|
+
k++;
|
104
|
+
} else {
|
105
|
+
var _RHS = subset(D, index(all, k));
|
106
|
+
for (var _j = 0; _j < k; _j++) {
|
107
|
+
_RHS = add(_RHS, multiply(y[_j], subset(G, index(_j, k))));
|
108
|
+
}
|
109
|
+
var _gkk = subset(G, index(k, k));
|
110
|
+
var _LHS = subtract(F, multiply(_gkk, identity(m)));
|
111
|
+
y[k] = lusolve(_LHS, _RHS);
|
112
|
+
}
|
113
|
+
}
|
114
|
+
var Y = matrix(matrixFromColumns(...y));
|
115
|
+
var X = multiply(U, multiply(Y, transpose(V)));
|
116
|
+
return X;
|
117
|
+
}
|
118
|
+
});
|
@@ -33,7 +33,7 @@ export var createForEach = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
33
33
|
return typed(name, {
|
34
34
|
'Array, function': _forEach,
|
35
35
|
'Matrix, function': function MatrixFunction(x, callback) {
|
36
|
-
|
36
|
+
x.forEach(callback);
|
37
37
|
}
|
38
38
|
});
|
39
39
|
});
|
@@ -49,7 +49,7 @@ export var createReshape = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
49
49
|
*/
|
50
50
|
return typed(name, {
|
51
51
|
'Matrix, Array': function MatrixArray(x, sizes) {
|
52
|
-
return x.reshape(sizes);
|
52
|
+
return x.reshape(sizes, true);
|
53
53
|
},
|
54
54
|
'Array, Array': function ArrayArray(x, sizes) {
|
55
55
|
sizes.forEach(function (size) {
|