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

Function reduceElementIndexingSets

src/compute-engine/library/utils.ts:665–793  ·  view source on GitHub ↗

* Handle Element-based indexing sets by extracting finite domains * and iterating over their values. * * Returns a detailed result to distinguish between: * - Success: domain was enumerated and reduced * - Non-enumerable: domain is valid but cannot be enumerated (keep expression symbolic) * -

(
  body: Expression,
  indexes: ReadonlyArray<Expression>,
  fn: (acc: T, x: Expression) => T | null,
  initial: T,
  returnReason = false
  // Yields only accumulator values (`T | undefined`) between iterations; the
  // detailed `ReduceElementResult` classification is delivered as the *return*
  // value. Splitting yield/return types lets `reduceBigOp` re-yield each
  // accumulator (for deadline checks) without widening its own yield type.
)

Source from the content-addressed store, hash-verified

663 return undefined;
664 if (!isFunction(body, 'Power')) return undefined;
665 const base = body.op1;
666 const exp = body.op2;
667 if (!(isSymbol(base) && base.symbol === index)) return undefined;
668 if (!isNumber(exp) || exp.im !== 0) return undefined;
669 const r = exp.re;
670 // s = −exp must be a real > 1 for absolute convergence (s = 1 is the
671 // harmonic/ζ(1) pole; s ≤ 1 diverges).
672 if (!(Number.isFinite(r) && r < -1)) return undefined;
673 const s = exp.neg();
674 const z = ce.function('Zeta', [s]).evaluate();
675 if (lowerValue === 1) return asReadableFraction(z, ce);
676
677 const terms: Expression[] = [z];
678 for (let k = 1; k < lowerValue; k++)
679 terms.push(
680 body
681 .subs({ [index]: k })
682 .evaluate()
683 .neg()
684 );
685 return asReadableFraction(ce.function('Add', terms).evaluate(), ce);
686}
687
688/**
689 * Closed form of a geometric series `Σ_{k=n₀}^∞ c·rᵏ = c·r^{n₀}/(1 − r)`, valid
690 * for `|r| < 1` (conditional-values design, Phase 3a). `r` must be free of the
691 * index `k`; `n₀` is an integer-literal lower bound; an index-free constant
692 * factor `c` is allowed (`c·rᵏ`).
693 *
694 * The convergence condition `|r| < 1` is routed through the `conditionalValue`
695 * chokepoint:
696 * - numeric `r` with `|r| < 1` → the bare exact value (per the exactness
697 * contract: `Σ(1/2)ᵏ → 2`, not `2.`);
698 * - numeric `r` with `|r| ≥ 1` → `undefined` (decidable-divergent: caller
699 * keeps the sum symbolic, mirroring the p-series entry);
700 * - symbolic `r` → `When(c·r^{n₀}/(1 − r), |r| < 1)`.
701 *
702 * Scope is deliberately just this family: no x-dependent ratios (`Σ n·xⁿ`),
703 * symbolic start indices, or derivative-of-geometric shapes.
704 */
705function geometricSumClosedForm(
706 body: Expression,
707 index: string,
708 lower: Expression,
709 ce: ComputeEngine
710): Expression | undefined {
711 if (!lower.isInteger) return undefined;
712 const n0 = lower.re;
713 if (!Number.isSafeInteger(n0)) return undefined;
714
715 // Separate an optional index-free constant factor `c` from the `rᵏ` power.
716 let coeff: Expression = ce.One;
717 let power: Expression = body;
718 if (isFunction(body, 'Multiply')) {
719 const consts: Expression[] = [];
720 const varying: Expression[] = [];
721 for (const f of body.ops) (f.has(index) ? varying : consts).push(f);
722 if (varying.length !== 1) return undefined;

Callers 1

reduceBigOpFunction · 0.85

Calls 8

isSymbolFunction · 0.90
normalizeIndexingSetFunction · 0.85
fnFunction · 0.85
numberMethod · 0.65
mapMethod · 0.65
assignMethod · 0.65

Tested by

no test coverage detected