A condition on a bound name stays in its binder - #1633
Conversation
A node's domain condition was the conjunction of its children's, a binder's body included, so
what a sum's body said about its index came out of the sum with the index free in it. The product
rule leaves 0 * sum(...), and 0 * f keeps the condition f is defined under, so the derivative of
2 sum(ln(x - w), w in { w : w^3 + w + 1 = 0 }) was "... provided not x - w = 0", which
EvalNumerical could not decide. sum(1/(k - x), k, 1, 3) and integral(1/(t - x), t, 0, 1) reported
"not k - x = 0" and "not t - x = 0" the same way; being expanded or evaluated first hid it there.
Such a conjunct is now read the way the binder reads it, as required at every value the name
ranges over, rather than left free or left out: left out, 0 * sum(1/(k - x), k, 1, n) became a
plain 0 at x = 1, where the sum has no value. Over the roots of a polynomial p with rational
coefficients, "q(w) != 0 at every root" is Res_w(p, q) != 0, which mentions the other names alone:
"not x^3 + x + 1 = 0" above, where the logarithms are singular. A finite range of numbers is the
conjunction over it. Anything else is forall over the range: the set of a sum over a set, of an
extremum or of a quantifier; the whole numbers between a summation's or a product's bounds; the
interval of a definite integral. A set builder's own condition on its name is part of whom it
admits, and is left out of where the set is defined. A limit does not need its body defined
throughout anything, and is left as it was.
BinderConditionTest pins each reading: the derivative has no free w and evaluates; over the roots
of w^2 - 1 the condition is false at 1 and -1 and true elsewhere, 0 included; the root polynomial itself as the
condition is defined nowhere; 0 * sum(1/(k - x), k, 1, n) keeps its condition; 1..3 is the
conjunction and 3..1 is empty; a set builder keeps nothing of its own.
Closes #1632.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
The resultant path is right, including where q's leading coefficient vanishes: Res(p, q) = lc(p)^m ∏ q(α) holds for any coefficients of q once p is fixed with a nonzero leading coefficient, and AtEveryRoot itself requires rational coefficients through SquareFreeParts, so a set builder typed with symbolic coefficients falls through to forall. The finite conjunction, 3..1 being empty and the set builder's reading are right too. Two things in the integral path:
1. Reversed limits look as though they lose the condition (inferred from the code, not yet probed). The range is MathS.Interval(from, to), and here an interval whose left end is above its right end reads as empty ((3; 1) /\ [0; 5] is { }). If [1; 0] does too, integral(1/(t - x), t, 1, 0) gets forall t in [1; 0] : …, which holds vacuously, and 0 * integral(1/(t - x), t, 1, 0) becomes a plain 0 at x = 1/2, which is the direction this PR exists to close. The segment between the limits in either order, MathS.Interval(from, to).Unite(MathS.Interval(to, from)), is right for symbolic limits as well.
2. Definedness on the closed interval is sufficient for a definite integral, not necessary. integral(ln(t), t, 0, 1) is -1, yet its condition is now forall t in [0; 1] : not t = 0, which is false. So the product rule's 0 * integral(…) should now be 0 provided false, and "2 * integral(x * ln(t), t, 0, 1)".Differentiate("x"), which is -2, should come out undefined. That is the same product-rule path as the RT derivative. Worth probing on the branch:
"2 * integral(x * ln(t), t, 0, 1)".Differentiate("x") // -2
"0 * integral(ln(t), t, 0, 1)" // 0
"0 * integral(1/t, t, 0, 1)" // undefined: it diverges
The open interval does not fix it: it answers the second row and gives the third a value. No condition on the integrand's points decides whether an improper integral converges, so whichever reading is chosen, I'd state it in the doc comment and the BREAKING entry and pin one example of each direction, so the limitation is visible rather than silent.
Tests. Nothing in BinderConditionTest reaches Integralf, though the BREAKING table lists one. AZeroTimesASumKeepsTheSumsCondition asserts the shape (Providedf, no k); asserting the meaning would bind it: with n = 3, undefined at x = 1 and 0 at x = 1/2.
MathS.Interval(1, 0) is empty, so forall t in [1; 0] was true of anything, and
0 * integral(1/(t - x), t, 1, 0) had a value at x = 1/2. Two numeric limits are put in order now, and
symbolic ones are written as the values between the two, since [a; b] \/ [b; a] simplifies to { b }.
Required throughout the segment, the condition is sufficient for a value and not necessary: ln(t)
over [0; 1] converges, and its condition reads it as undefined. That is the direction in which
nothing gets a value it does not have, and the doc comment and BREAKING-CHANGES.md say so.
BinderConditionTest gains the integral in both orders at 1/2 and at 2, symbolic limits, ln(t) over
[0; 1] and over [1; 2], and the value of 0 * sum(1/(k - x), k, 1, n) at x = 1, which is none, and
at x = 1/2, which is 0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Both points held, and are fixed in 8d8d3e8.
Also added, as you asked: the integral in both orders at 1/2 and at 2, symbolic limits, and |
Rafael-SOWNet
left a comment
There was a problem hiding this comment.
Both points are addressed in 8d8d3e8. Numeric limits are put in order, and symbolic ones become the values between them in either order. The closed-segment reading is stated as sufficient, not necessary, and ln(t) is pinned over [0; 1] and [1; 2]. The 0 * sum case is now asserted by value. Looks right to me. The union this exposed, [0; 1] \/ [1; 0] giving { 1 }, is #1634, and I'm taking it.
…OT compiles The Sylvester determinant was a MathS.Matrix of entities, and its determinant runs through GenericTensor, whose expression compiler native AOT cannot compile (IL3050): reached from DomainCondition, a property every node has, it failed every native build. Past a linear the resultant is taken only for rational coefficients now, where it is a number and only whether it is zero matters, by Bareiss's fraction-free elimination in whole numbers. A q of higher degree with symbolic coefficients is left to forall. The native publish of AngouriMath.CPP.Exporting for linux-x64 compiles again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The native builds failed on the previous head: |
A node's domain condition was the conjunction of its children's, a binder's body included, so what a sum's body said about its index came out of the sum with the index free in it:
0 * sum(...), and0 * fkeeps the conditionfis defined under. So the derivative of2 sum(ln(x - w), w in { w : w^3 + w + 1 = 0 })was… provided not x - w = 0, withwfree, andEvalNumericalcould not decide it.sum(1/(k - x), k, 1, 3)andintegral(1/(t - x), t, 0, 1)reportednot k - x = 0andnot t - x = 0the same way. Being expanded or evaluated first hid it there.Such a conjunct is now read the way the binder reads it, as required at every value the name ranges over. It is not left free, and it is not left out: left out,
0 * sum(1/(k - x), k, 1, n)became a plain 0 atx = 1, where the sum has no value.pwith rational coefficients, "q(w) != 0at every root" isRes_w(p, q) != 0, which mentions the other names alone. Above it isnot x^3 + x + 1 = 0, where the logarithms are singular.forallover the range: the set of a sum over a set, of an extremum or of a quantifier; the whole numbers between a summation's or a product's bounds; the interval of a definite integral.Measured
"sum(1/(k - x), k, 1, 3)".ToEntity().DomainConditionnot k - x = 0not 1 - x = 0 and not 2 - x = 0 and not 3 - x = 0"sum(1/(k - x), k, 1, n)".ToEntity().DomainConditionnot k - x = 0forall k in { k : k in ZZ and 1 <= k and k <= n } : not k - x = 0"integral(1/(t - x), t, 0, 1)".ToEntity().DomainConditionnot t - x = 0forall t in [0; 1] : not t - x = 0"sum(ln(x - w), w in { w : w^3 + w + 1 = 0 })".ToEntity().DomainConditionnot -1 + -x + (-x) ^ 3 = 0BinderConditionTestpins each reading. The derivative has no freewand evaluates. Over the roots ofw^2 - 1, the condition is false at 1 and -1 and true elsewhere. The root polynomial itself as the condition is defined nowhere.0 * sum(1/(k - x), k, 1, n)keeps its condition.1..3is the conjunction and3..1is empty. A set builder keeps nothing of its own.Closes #1632.
🤖 Generated with Claude Code