Skip to content

A condition the answer states on its own is no longer repeated beside it - #1396

Merged
Rafael-SOWNet merged 2 commits into
masterfrom
provided-implied-by-the-expression
Sep 17, 2026
Merged

Rafael-SOWNet merged 2 commits into
masterfrom
provided-implied-by-the-expression

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

#1394: (1 − ln(x))/x^2 provided not x = 0 excludes a point the expression never reaches — the quotient by x^2 and the ln(x) are each undefined at zero already — and says twice what the expression says once. A provided whose condition the expression proves on its own comes back without that conjunct.

What is proven, and how. A condition not e = 0 is implied where the expression has a node undefined at every zero of e: a quotient by d, a negative power of d, a logarithm of d or to the base d, or d^f with f vanishing too — for d equal to e, a positive power of it, a product holding it, a polynomial in the variable e is with no constant term, or a polynomial that is zero at the root of a linear e. Structural and never guessed: a false negative is a redundant clause, a false positive would claim a value at a point. A condition the expression does not state is kept — x/x still simplifies to 1 provided not x = 0, since 1 no longer says it; 1/(x^2 + 1) provided not x = 0 keeps its condition, y/x provided not a x = 0 keeps its.

Where — and where not. Only the answer of Simplify, and only its top. Inside a piecewise a predicate decides which case is taken and falls through where it fails, so it is not redundant even when the case's expression is undefined without it. And inside the simplifier's own search a provided is what several rules read as "this candidate needs a condition": the first version dropped it in Providedf.InnerSimplify, and the substitution search then accepted candidates it had declined and ran x/sin(x) for a minute (candidates growing to ninth powers) where it declines in half a second. At Simplify's boundary the answer is the same and the search is untouched; the gate reads SimplifyEasy +0.6%, SimplifyHard +0.9%, all rows within threshold.

Was Is
"ln(x)/x".Differentiate("x").Simplify() (1 − ln(x))/x^2 provided not x = 0 (1 − ln(x))/x^2
"x^x".Differentiate("x").Simplify() (1 + ln(x)) x^x provided not x = 0 (1 + ln(x)) x^x
"x^n".Differentiate("x").Simplify() x^n n/x provided not x = 0 x^n n/x
"1/(x^2 + x) provided not x = 0 and not x + 1 = 0".Simplify() unchanged 1/(x^2 + x)
"(x + sin(x))/x".Limit("x", "+oo") unevaluated 1

The last row is a consequence worth naming: after the division the limit's integrand was 1 + sin(x)/x provided not x = 0, and the condition stood between the descent and the sum; without it the squeeze theorem answers sin(x)/x and the limit is 1. Two tests pinned the decline (GruntzTest, LimitAtInfinityTest, "no rule anywhere has a reading of it"); they now pin the answer in BoundedTimesVanishingTest, and x cos(x), x sin(x) stay declined.

On the two questions in the issue. Dropping is sound whichever way "undefined" is read — NaN today, a complex infinity under #217 — since a provided says the expression has no value where the condition fails, and nothing changes where it has none anyway; the two notions would differ only in what the value at the point is called, which a condition never gave. And it is a question of the domain (where the expression is defined), not the codomain: the codomain setting decides which branch or which real form is written (ln|x| against ln x), and a condition dropped or kept is the same statement under either.

Recorded in BREAKING-CHANGES.md as an improvement. Four suites green; the new ProvidedImpliedByTheExpressionTest pins eight drops, two derivatives, and three conditions that must stay.

Part of #1394.

🤖 Generated with Claude Code

https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

Rafael-SOWNet and others added 2 commits September 17, 2026 13:45
(1 - ln(x))/x^2 provided not x = 0 excludes a point the expression
never reaches: the quotient by x^2 and the ln(x) are each undefined at
zero already. A provided whose condition the expression proves on its
own -- a quotient by d, a negative power of d, a logarithm of d or to
the base d, or d^f with f vanishing too, for d the condition's e, a
positive power of it, a product holding it, a polynomial in the
variable e is with no constant term, or a polynomial that is zero at
the root of a linear e -- comes back without that conjunct. Proven
structurally and never guessed: a false negative is a redundant
clause, a false positive would claim a value at a point.

Only the answer is read this way, and only its top. Inside a piecewise
a predicate decides which case is taken and falls through to the next
where it fails, so it is not redundant even where the case's
expression is undefined without it. And inside the simplifier's own
search a provided is what several rules read as "this candidate needs
a condition": taken off there, in Providedf's InnerSimplify, the
substitution search accepted candidates it had declined and ran
x/sin(x) for a minute where it declines in half a second, with the
candidates growing to ninth powers on the way. At Simplify's boundary
the answer is the same and the search is untouched.

The derivatives of ln(x)/x, x^x and x^n lose the condition they
repeated (#1394, from the comparison page). One limit is answered by
it: (x + sin(x))/x at infinity was 1 + sin(x)/x provided not x = 0
after the division, and the condition stood between the descent and
the sum; it is 1 now, by the squeeze theorem, and the two tests that
pinned the decline pin the answer. Recorded in BREAKING-CHANGES.md as
an improvement.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
@Rafael-SOWNet
Rafael-SOWNet merged commit d3eda93 into master Sep 17, 2026
31 checks passed
@Rafael-SOWNet
Rafael-SOWNet deleted the provided-implied-by-the-expression branch September 17, 2026 14:31
Rafael-SOWNet added a commit that referenced this pull request Sep 17, 2026
…read in the codomain

#1396 decided by the shape of the node -- a quotient by d, a negative power of d, a logarithm
of d, d^f with f vanishing -- what the library already says per node: DomainConditionIn(codomain)
is what an expression accepts under the reading it is asked in, a nonzero divisor, a nonzero
base or a positive exponent, a nonzero antilogarithm over the complex plane and a positive one
over the reals, a cosine that is not zero for a tangent. A provided not e = 0 is redundant
where that domain condition already excludes the zeros of e: a conjunct not d = 0 or d > 0
with d vanishing there -- e itself, a positive power of it, a product holding it, a sine,
tangent, arcsine or arctangent of such a thing, or a polynomial in the variable e is with no
constant term -- or a disjunction every side of which does, as x^x's not x = 0 or x > 0.
Nothing in the rule decides what a node accepts, so it follows the codomain: when #217 gives
1/0 a value under the codomains that admit a complex infinity, the quotient's domain condition
changes there and the condition beside 1/x stops being redundant by itself.

The answers are #1396's, and the shapes the list missed: tan(x) provided not cos(x) = 0 and
sin(x)/x provided not x = 0 drop their conditions too. Recorded in the Providedf section of
SimplificationContract.md, in the comparison page's provided paragraph and in the #1396 entry
of BREAKING-CHANGES. Four suites green; the performance gate passed.

Part of #1394.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
Rafael-SOWNet added a commit that referenced this pull request Sep 17, 2026
…read in the codomain (#1402)

* A pole is a value, so only an indeterminate form lets Simplify drop the condition beside it

#1394's reading: a provided says where the expression has a value, and 1/x at zero has one,
the point at infinity, so 1/x provided not x = 0 is a different expression from 1/x and keeps
its condition. #1396 dropped it, reading a quotient by d, a negative power of d and a logarithm
of d as undefined at the zeros of d; those arms go, and only 0^0 and 0/0 -- d^f or n/d with
both vanishing at the zeros of the condition's expression -- are read, a sine, tangent,
arcsine or arctangent of something vanishing counting as vanishing. x^x's derivative stays
bare, ln(x)/x's derivative keeps its condition as before #1396, and (x + sin(x))/x still has
limit 1 at infinity since sin(x)/x is 0/0 at zero.

The reading is recorded in the Providedf section of SimplificationContract.md, with the
codomain caveat, in the comparison page's provided paragraph, and in the #1396 entry of
BREAKING-CHANGES, rewritten to the net behaviour with the day the wider rule stood on master
noted. Four suites green; the performance gate passed.

Part of #1394.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

* Simplify drops a condition the answer's own domain condition states, read in the codomain

#1396 decided by the shape of the node -- a quotient by d, a negative power of d, a logarithm
of d, d^f with f vanishing -- what the library already says per node: DomainConditionIn(codomain)
is what an expression accepts under the reading it is asked in, a nonzero divisor, a nonzero
base or a positive exponent, a nonzero antilogarithm over the complex plane and a positive one
over the reals, a cosine that is not zero for a tangent. A provided not e = 0 is redundant
where that domain condition already excludes the zeros of e: a conjunct not d = 0 or d > 0
with d vanishing there -- e itself, a positive power of it, a product holding it, a sine,
tangent, arcsine or arctangent of such a thing, or a polynomial in the variable e is with no
constant term -- or a disjunction every side of which does, as x^x's not x = 0 or x > 0.
Nothing in the rule decides what a node accepts, so it follows the codomain: when #217 gives
1/0 a value under the codomains that admit a complex infinity, the quotient's domain condition
changes there and the condition beside 1/x stops being redundant by itself.

The answers are #1396's, and the shapes the list missed: tan(x) provided not cos(x) = 0 and
sin(x)/x provided not x = 0 drop their conditions too. Recorded in the Providedf section of
SimplificationContract.md, in the comparison page's provided paragraph and in the #1396 entry
of BREAKING-CHANGES. Four suites green; the performance gate passed.

Part of #1394.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant