|
34 | 34 |
|
35 | 35 | - **Absolute Value Power Simplification**: Fixed simplification of `|x^n|` |
36 | 36 | expressions with even and rational exponents. Previously, expressions like |
37 | | - `|x²|` and `|x^{2/3}|` were not simplified. Now they correctly simplify |
38 | | - based on the parity of the exponent's numerator. Addresses #181. |
| 37 | + `|x²|` and `|x^{2/3}|` were not simplified. Now they correctly simplify based |
| 38 | + on the parity of the exponent's numerator. Addresses #181. |
39 | 39 |
|
40 | 40 | ```javascript |
41 | 41 | ce.parse('|x^2|').simplify().latex; // → "x^2" (even exponent) |
|
65 | 65 |
|
66 | 66 | - **Non-linear Polynomial Systems**: The `solve()` method now handles certain |
67 | 67 | non-linear polynomial systems with 2 equations and 2 variables: |
68 | | - |
69 | 68 | - **Product + sum pattern**: Systems like `xy = p, x + y = s` are solved by |
70 | 69 | recognizing that x and y are roots of the quadratic `t² - st + p = 0`. |
71 | 70 |
|
|
123 | 122 | // → [{ x: 0, y: 0 }, { x: 5, y: 0 }, { x: 5, y: 5 }, { x: 0, y: 5 }] |
124 | 123 | ``` |
125 | 124 |
|
126 | | - Vertices are returned in counterclockwise convex hull order. Returns `null` for |
127 | | - infeasible systems or non-linear constraints. |
| 125 | + Vertices are returned in counterclockwise convex hull order. Returns `null` |
| 126 | + for infeasible systems or non-linear constraints. |
128 | 127 |
|
129 | 128 | - **Under-determined Systems (Parametric Solutions)**: The `solve()` method now |
130 | 129 | returns parametric solutions for under-determined linear systems (fewer |
131 | 130 | equations than variables) instead of returning `null`. Free variables appear |
132 | | - as themselves in the solution, with other variables expressed in terms of them. |
| 131 | + as themselves in the solution, with other variables expressed in terms of |
| 132 | + them. |
133 | 133 |
|
134 | 134 | ```javascript |
135 | 135 | // Single equation with two variables |
|
146 | 146 | Inconsistent systems still return `null`. |
147 | 147 |
|
148 | 148 | - **Extended Sqrt Equation Solving**: The equation solver now handles sqrt |
149 | | - equations of the form `√(f(x)) = g(x)` by squaring both sides and solving |
150 | | - the resulting polynomial. Extraneous roots are automatically filtered. |
| 149 | + equations of the form `√(f(x)) = g(x)` by squaring both sides and solving the |
| 150 | + resulting polynomial. Extraneous roots are automatically filtered. |
151 | 151 |
|
152 | 152 | ```javascript |
153 | 153 | ce.parse('\\sqrt{x+1} = x').solve('x'); // → [1.618...] (golden ratio) |
|
156 | 156 | ce.parse('\\sqrt{x} = x').solve('x'); // → [0, 1] |
157 | 157 | ``` |
158 | 158 |
|
159 | | -- **Two Sqrt Equation Solving**: The equation solver now handles equations |
160 | | - with two sqrt terms of the form `√(f(x)) + √(g(x)) = e` using double squaring. |
161 | | - Both addition and subtraction forms are supported, and extraneous roots are |
| 159 | +- **Two Sqrt Equation Solving**: The equation solver now handles equations with |
| 160 | + two sqrt terms of the form `√(f(x)) + √(g(x)) = e` using double squaring. Both |
| 161 | + addition and subtraction forms are supported, and extraneous roots are |
162 | 162 | automatically filtered. |
163 | 163 |
|
164 | 164 | ```javascript |
|
168 | 168 | ce.parse('\\sqrt{2x+1} + \\sqrt{x-1} = 4').solve('x'); // → [46 - 8√29] ≈ 2.919 |
169 | 169 | ``` |
170 | 170 |
|
171 | | -- **Nested Sqrt Equation Solving**: The equation solver now handles nested |
172 | | - sqrt equations of the form `√(x + √x) = a` using substitution. These patterns |
173 | | - have √x inside the argument of an outer sqrt. The solver uses u = √x |
174 | | - substitution, solves the resulting quadratic, and filters negative u values. |
| 171 | +- **Nested Sqrt Equation Solving**: The equation solver now handles nested sqrt |
| 172 | + equations of the form `√(x + √x) = a` using substitution. These patterns have |
| 173 | + √x inside the argument of an outer sqrt. The solver uses u = √x substitution, |
| 174 | + solves the resulting quadratic, and filters negative u values. |
175 | 175 |
|
176 | 176 | ```javascript |
177 | 177 | ce.parse('\\sqrt{x + 2\\sqrt{x}} = 3').solve('x'); // → [11 - 2√10] ≈ 4.675 |
|
180 | 180 | ``` |
181 | 181 |
|
182 | 182 | - **Quadratic Equations Without Constant Term**: Added support for solving |
183 | | - quadratic equations of the form `ax² + bx = 0` (missing constant term). |
184 | | - These are solved by factoring: `x(ax + b) = 0` → `x = 0` or `x = -b/a`. |
| 183 | + quadratic equations of the form `ax² + bx = 0` (missing constant term). These |
| 184 | + are solved by factoring: `x(ax + b) = 0` → `x = 0` or `x = -b/a`. |
185 | 185 |
|
186 | 186 | ```javascript |
187 | 187 | ce.parse('x^2 + 3x = 0').solve('x'); // → [0, -3] |
188 | 188 | ce.parse('2x^2 - 4x = 0').solve('x'); // → [0, 2] |
189 | 189 | ``` |
190 | 190 |
|
191 | | -- **Value Resolution from Equality Assumptions**: When an equality assumption |
192 | | - is made via `ce.assume(['Equal', symbol, value])`, the symbol now correctly |
| 191 | +- **Value Resolution from Equality Assumptions**: When an equality assumption is |
| 192 | + made via `ce.assume(['Equal', symbol, value])`, the symbol now correctly |
193 | 193 | evaluates to the assumed value. Previously, the symbol would remain unchanged |
194 | 194 | even after the assumption. |
195 | 195 |
|
|
204 | 204 | This also fixes comparison evaluation: `Equal(symbol, assumed_value)` now |
205 | 205 | correctly evaluates to `True` instead of staying symbolic. |
206 | 206 |
|
207 | | -- **Inequality Evaluation Using Assumptions**: When an inequality assumption |
208 | | - is made (e.g., `ce.assume(['Greater', 'x', 4])`), inequality comparisons |
209 | | - can now use transitive reasoning to determine results. |
| 207 | +- **Inequality Evaluation Using Assumptions**: When an inequality assumption is |
| 208 | + made (e.g., `ce.assume(['Greater', 'x', 4])`), inequality comparisons can now |
| 209 | + use transitive reasoning to determine results. |
210 | 210 |
|
211 | 211 | ```javascript |
212 | 212 | ce.assume(ce.box(['Greater', 'x', 4])); |
|
216 | 216 | ce.box('x').isPositive; // → true |
217 | 217 | ``` |
218 | 218 |
|
219 | | - This works by extracting lower/upper bounds from inequality assumptions |
220 | | - and using them during comparison operations. |
| 219 | + This works by extracting lower/upper bounds from inequality assumptions and |
| 220 | + using them during comparison operations. |
221 | 221 |
|
222 | 222 | - **Type Inference from Assumptions**: When assumptions are made, symbol types |
223 | 223 | are now correctly inferred. Inequality assumptions (`>`, `<`, `>=`, `<=`) set |
|
234 | 234 |
|
235 | 235 | - **Tautology and Contradiction Detection**: `ce.assume()` now returns |
236 | 236 | `'tautology'` for redundant assumptions that are already implied by existing |
237 | | - assumptions, and `'contradiction'` for assumptions that conflict with |
238 | | - existing ones. |
| 237 | + assumptions, and `'contradiction'` for assumptions that conflict with existing |
| 238 | + ones. |
239 | 239 |
|
240 | 240 | ```javascript |
241 | 241 | ce.assume(ce.box(['Greater', 'x', 4])); |
|
268 | 268 | // → 2x + b (was: 2 - incorrectly matched entire expression) |
269 | 269 | ``` |
270 | 270 |
|
271 | | -- **forget() Now Clears Assumed Values**: Fixed an issue where `ce.forget()` did not |
272 | | - clear values that were set by equality assumptions. After calling |
| 271 | +- **forget() Now Clears Assumed Values**: Fixed an issue where `ce.forget()` did |
| 272 | + not clear values that were set by equality assumptions. After calling |
273 | 273 | `ce.assume(['Equal', 'x', 5])` followed by `ce.forget('x')`, the symbol would |
274 | 274 | incorrectly still evaluate to `5`. Now `forget()` properly clears values from |
275 | 275 | all evaluation context frames. |
|
314 | 314 |
|
315 | 315 | - **Pattern Matching with Repeated Wildcards**: Added comprehensive tests |
316 | 316 | verifying that the pattern matching system correctly handles wildcards that |
317 | | - appear multiple times in a pattern. When a named wildcard like `_x` appears |
318 | | - in multiple positions, the matcher correctly ensures all occurrences match |
319 | | - the same expression. This works with: |
| 317 | + appear multiple times in a pattern. When a named wildcard like `_x` appears in |
| 318 | + multiple positions, the matcher correctly ensures all occurrences match the |
| 319 | + same expression. This works with: |
320 | 320 | - Nested function arguments (e.g., `['Multiply', '_x', ['Ln', '_x']]`) |
321 | 321 | - Multiple nesting levels (3+ levels deep) |
322 | 322 | - Commutative operators (handles reordering) |
|
347 | 347 | ``` |
348 | 348 |
|
349 | 349 | Both simple subscripts (`F_5`) and complex subscripts (`F_{5}`) are supported. |
350 | | - When the handler returns `undefined`, the expression stays symbolic. Subscripted |
351 | | - expressions with `subscriptEvaluate` have type `number` and can be used in |
352 | | - arithmetic operations: `ce.parse('F_{5} + F_{3}').evaluate()` works correctly. |
| 350 | + When the handler returns `undefined`, the expression stays symbolic. |
| 351 | + Subscripted expressions with `subscriptEvaluate` have type `number` and can be |
| 352 | + used in arithmetic operations: `ce.parse('F_{5} + F_{3}').evaluate()` works |
| 353 | + correctly. |
353 | 354 |
|
354 | 355 | - **Type-Aware Subscript Handling**: Subscripts on symbols declared as |
355 | 356 | collection types (list, tuple, matrix, etc.) now automatically convert to |
|
435 | 436 | - Domain constraints (min/max valid indices) |
436 | 437 | - Symbolic subscripts stay symbolic (e.g., `F_k` remains unevaluated) |
437 | 438 |
|
438 | | - Alternatively, sequences can be defined using natural LaTeX assignment notation: |
| 439 | + Alternatively, sequences can be defined using natural LaTeX assignment |
| 440 | + notation: |
439 | 441 |
|
440 | 442 | ```javascript |
441 | 443 | // Arithmetic sequence via LaTeX |
|
520 | 522 | ``` |
521 | 523 |
|
522 | 524 | - **OEIS Integration**: Look up sequences in the Online Encyclopedia of Integer |
523 | | - Sequences (OEIS) and verify your sequences against known mathematical sequences: |
| 525 | + Sequences (OEIS) and verify your sequences against known mathematical |
| 526 | + sequences: |
524 | 527 |
|
525 | 528 | ```javascript |
526 | 529 | // Look up a sequence by its terms |
|
539 | 542 |
|
540 | 543 | Note: OEIS lookups require network access to oeis.org. |
541 | 544 |
|
542 | | -- **Multi-Index Sequences**: Define sequences with multiple indices like Pascal's |
543 | | - triangle P_{n,k} or grid-based recurrences: |
| 545 | +- **Multi-Index Sequences**: Define sequences with multiple indices like |
| 546 | + Pascal's triangle P\_{n,k} or grid-based recurrences: |
544 | 547 |
|
545 | 548 | ```javascript |
546 | 549 | // Pascal's Triangle: P_{n,k} = P_{n-1,k-1} + P_{n-1,k} |
|
558 | 561 |
|
559 | 562 | Features: |
560 | 563 | - Multiple index variables with `variables: ['n', 'k']` |
561 | | - - Pattern-based base cases: `'n,0'` matches any (n, 0), `'n,n'` matches diagonal |
| 564 | + - Pattern-based base cases: `'n,0'` matches any (n, 0), `'n,n'` matches |
| 565 | + diagonal |
562 | 566 | - Per-variable domain constraints |
563 | 567 | - Constraint expressions (e.g., `'k <= n'`) |
564 | 568 | - Composite key memoization (e.g., `'5,2'`) |
|
572 | 576 |
|
573 | 577 | #### Special Functions |
574 | 578 |
|
575 | | -- **Special Function Definitions**: Added type signatures for special mathematical |
576 | | - functions, enabling them to be used in expressions without type errors: |
| 579 | +- **Special Function Definitions**: Added type signatures for special |
| 580 | + mathematical functions, enabling them to be used in expressions without type |
| 581 | + errors: |
577 | 582 | - `Zeta` - Riemann zeta function ζ(s) |
578 | 583 | - `Beta` - Euler beta function B(a,b) = Γ(a)Γ(b)/Γ(a+b) |
579 | 584 | - `LambertW` - Lambert W function (product logarithm) |
|
596 | 601 |
|
597 | 602 | - **Bessel Function Derivatives**: Added derivative support for all four Bessel |
598 | 603 | function types using order-dependent recurrence relations: |
| 604 | + |
599 | 605 | ```javascript |
600 | 606 | ce.box(['D', ['BesselJ', 'n', 'x'], 'x']).evaluate(); |
601 | 607 | // → 1/2 * BesselJ(n-1, x) - 1/2 * BesselJ(n+1, x) |
|
606 | 612 | ce.box(['D', ['BesselK', 'n', 'x'], 'x']).evaluate(); |
607 | 613 | // → -1/2 * BesselK(n-1, x) - 1/2 * BesselK(n+1, x) |
608 | 614 | ``` |
| 615 | + |
609 | 616 | Chain rule is automatically applied for composite arguments. |
610 | 617 |
|
611 | 618 | - **Multi-Argument Function Derivatives**: Added derivative support for: |
612 | | - |
613 | 619 | - **Log(x, base)** - Logarithm with custom base: |
| 620 | + |
614 | 621 | ```javascript |
615 | 622 | ce.box(['D', ['Log', 'x', 2], 'x']).evaluate(); // → 1/(x·ln(2)) |
616 | 623 | ce.box(['D', ['Log', 'x', 'a'], 'x']).evaluate(); // → 1/(x·ln(a)) |
617 | 624 | ``` |
| 625 | + |
618 | 626 | Also handles cases where both x and base depend on the variable by applying |
619 | 627 | the quotient rule to ln(x)/ln(base). |
620 | 628 |
|
|
626 | 634 | ``` |
627 | 635 |
|
628 | 636 | - **Integration of `1/(x·ln(x))` Pattern**: Added support for integrating |
629 | | - expressions where the denominator is a product and one factor is the derivative |
630 | | - of another: |
| 637 | + expressions where the denominator is a product and one factor is the |
| 638 | + derivative of another: |
| 639 | + |
631 | 640 | ```javascript |
632 | 641 | ce.parse('\\int \\frac{1}{x\\ln x} dx').evaluate(); // → ln(|ln(x)|) |
633 | 642 | ce.parse('\\int \\frac{3}{x\\ln x} dx').evaluate(); // → 3·ln(|ln(x)|) |
634 | 643 | ``` |
| 644 | + |
635 | 645 | This uses u-substitution: since `1/x = d/dx(ln(x))`, the integral becomes |
636 | 646 | `∫ h'(x)/h(x) dx = ln|h(x)|`. |
637 | 647 |
|
638 | 648 | - **Cyclic Integration for e^x with Trigonometric Functions**: Added support for |
639 | 649 | integrating products of exponentials and trigonometric functions that require |
640 | 650 | the "solve for the integral" technique: |
| 651 | + |
641 | 652 | ```javascript |
642 | 653 | ce.parse('\\int e^x \\sin x dx').evaluate(); |
643 | 654 | // → -1/2·cos(x)·e^x + 1/2·sin(x)·e^x |
|
652 | 663 | ce.parse('\\int e^x \\cos(2x) dx').evaluate(); |
653 | 664 | // → 1/5·cos(2x)·e^x + 2/5·sin(2x)·e^x |
654 | 665 | ``` |
| 666 | + |
655 | 667 | These patterns cannot be solved by standard integration by parts (which would |
656 | 668 | lead to infinite recursion) and instead use direct formulas: |
657 | 669 | - `∫ e^x·sin(ax+b) dx = (e^x/(a²+1))·(sin(ax+b) - a·cos(ax+b))` |
|
669 | 681 | - **Double negation**: `¬¬A → A` |
670 | 682 |
|
671 | 683 | These rules are applied automatically during simplification: |
| 684 | + |
672 | 685 | ```javascript |
673 | 686 | ce.box(['And', 'A', ['Or', 'A', 'B']]).simplify(); // → A |
674 | 687 | ce.box(['Or', 'A', ['And', 'A', 'B']]).simplify(); // → A |
|
703 | 716 | - **Matrix Decompositions**: Added four matrix decomposition functions for |
704 | 717 | numerical linear algebra: |
705 | 718 | - `LUDecomposition(A)` → `[P, L, U]` - LU factorization with partial pivoting |
706 | | - - `QRDecomposition(A)` → `[Q, R]` - QR factorization using Householder reflections |
707 | | - - `CholeskyDecomposition(A)` → `L` - Cholesky factorization for positive definite matrices |
| 719 | + - `QRDecomposition(A)` → `[Q, R]` - QR factorization using Householder |
| 720 | + reflections |
| 721 | + - `CholeskyDecomposition(A)` → `L` - Cholesky factorization for positive |
| 722 | + definite matrices |
708 | 723 | - `SVD(A)` → `[U, Σ, V]` - Singular Value Decomposition |
709 | 724 |
|
710 | 725 | ```javascript |
|
0 commit comments