MCPcopy Create free account
hub / github.com/cortex-js/compute-engine / validateRoots

Function validateRoots

src/compute-engine/boxed-expression/solve.ts:2571–2626  ·  view source on GitHub ↗
(
  expr: Expression,
  x: string,
  roots: ReadonlyArray<Expression>,
  trace?: RuleSteps
)

Source from the content-addressed store, hash-verified

2569 // decidable guard for the narrative (a numeric ratio collapses to the
2570 // bare root, matching the pre-Phase-2 trace; a False guard drops the
2571 // step). An undecidable guard is displayed as the `When`.
2572 let value: Expression | null = m.value;
2573 if (isFunction(value, 'When'))
2574 value = conditionalRoot(ce, value.op1, value.op2);
2575 if (value === null) continue;
2576 traceStep(
2577 trace,
2578 m.because !== '' ? m.because : 'solve.template',
2579 rootsAsEquations(ce, x, [value])
2580 );
2581 }
2582 };
2583
2584 // FAST PATH: a univariate polynomial of degree ≥ 2 is solved directly from
2585 // its coefficients (quadratic formula / rational-root + numeric), skipping
2586 // the commutative pattern-matcher whose operand-permutation search dominates
2587 // polynomial solving (P1-2). Non-polynomial shapes — and linear equations,
2588 // whose rule is already cheap — fall through to the rule templates below.
2589 // `originalExpr` is preferred (clean); when radical-clearing turned a
2590 // non-polynomial original into a sqrt-free polynomial (`√(1−x²) = x²` →
2591 // `1 − x² − x⁴`), the transformed `expr` is used and `validateRoots` drops
2592 // any roots the squaring introduced.
2593 const polyExpr =
2594 polynomialDegree(originalExpr, x) >= 0
2595 ? originalExpr
2596 : polynomialDegree(expr, x) >= 0
2597 ? expr
2598 : null;
2599 if (polyExpr !== null && polynomialDegree(polyExpr, x) >= 2)
2600 result = solvePolynomialByCoefficients(polyExpr, x, trace);
2601
2602 if (result.length === 0) {
2603 for (const e of exprs) {
2604 const matches = matchRootsSteps(e);
2605 traceMatches(matches);
2606 result.push(...matches.map((s) => s.value));
2607 }
2608 }
2609
2610 // If we didn't find a solution yet, try modifying the expression
2611 //expr.
2612 // Note: @todo we can try different heuristics here:
2613 // Collection: reduce the numbers of occurrences of the unknown
2614 // Attraction: bring the occurrences of the unknown closer together
2615 // Function Swapping: replacing function with ones easier to solve
2616 // - square roots: square both sides
2617 // - logs: exponentiate both sides
2618 // - trig functions: use inverse trig functions
2619 // Homogenization: replace a function of the unknown by a new variable,
2620 // e.g. exp(x) -> y, then solve for y
2621
2622 let harmonized: Expression[] = [];
2623 if (result.length === 0) {
2624 harmonized = exprs.flatMap((expr) => harmonize(expr));
2625 for (const h of harmonized) {
2626 const matches = matchRootsSteps(h);
2627 traceMatches(matches, { because: 'solve.harmonize', form: h });
2628 result.push(...matches.map((s) => s.value));

Callers 1

findUnivariateRootsFunction · 0.85

Calls 8

traceStepFunction · 0.85
rootsAsEquationsFunction · 0.85
evaluateMethod · 0.65
subsMethod · 0.65
hasMethod · 0.65
isEqualMethod · 0.65
simplifyMethod · 0.65
isSameMethod · 0.65

Tested by

no test coverage detected