Repository navigation
Differentiate what does not mention the variable to 0, whatever its node - #2014
Merged
Rafael-SOWNet merged 1 commit intoOct 21, 2026
Merged
Rafael-SOWNet merged 1 commit into
Rafael-SOWNet merged 1 commit into
Conversation
Every rule differentiated its parts by calling InnerDifferentiate directly, and only the base rule knew that an x-free node differentiates to 0. So a power, a function, a logarithm or a quotient with no x in it went through the chain rule, and InnerSimplified folded 0 * f' into `0 provided` where f' is defined: d/dx (a - a)^(1/2) and d/dx sqrt(a) x at a = 0 were NaN, and so were arcsin(a) x at a = 1, ln(c - c) and 1/(a - a). DerivativeOver now answers 0 for a node without the variable and without a set, a matrix, a provided, a piecewise or a written NaN, which keep their own rules, and all 47 child calls go through it. The integrator relied on the spurious conditions in four places, which are now explicit. SolveByEulerSubstitution's perfect-square test asked a value and missed symbolic squares such as (2 a b)^2 - 4 b^2 a^2, and a root of a symbol in x(t) was in effect never taken; the test is now IsAPerfectSquareDiscriminant, and such a root is declined. Three routes that the conditions cut short now decline early by value: SolveByPartialFractions' logarithmic-derivative test (MayBeAConstantMultiple), a candidate even in x in SolveBySubstitution (it repeats at -x), and a substitution whose quotient keeps x through every rewriting (KeepsTheVariableThroughEveryRewriting). 1/(x sqrt(k^2 x^2 + 2 k x + 1)) had no value anywhere on master and is answered; 1/(x (a^2 + 2 a b x^3 + b^2 x^6)^(5/2)), answered with no value anywhere on master, is declined as 2.5.0 declined it. Chain against master a567c8b, a 4,231-row stride pocket over every family: allocation over the rows solved on both 825.5 -> 746.3 GB; 1.1.2.4:566 and 4.3.2.1:690 timeout -> 1.6 s and 0.65 s alone; 6.3.2:218 answered by Integrate itself; samples unchanged; no row's allocation grew past 1.3x. 6.7.1:897 0.38 GB, from 4.13. Part of #233. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #233.
Every rule differentiated its parts by calling
InnerDifferentiatedirectly, and only the base rule knew that a node without the variable differentiates to 0. So a power, a function, a logarithm or a quotient with no x in it went through the chain rule, andInnerSimplifiedfolded0 * f'into0 provided <where f' is defined>. The derivative was NaN where the expression has a value:.Differentiate("x")of(a - a)^(1/2)0 provided not a - a = 0, NaN0sqrt(a) * xsqrt(a)arcsin(a) * xarcsin(a)ln(c - c),1/(a - a)0The new
DerivativeOver(Variable)answers 0 for a node without the variable. Nodes containing a set, a matrix, aprovided, a piecewise or a written NaN are excluded and keep their own rules:{1, 2}still gives{0}, and a piecewise keeps its conditions. All 47 child calls now go through it. The protectedInnerDifferentiateoverrides keep their names, so the public API is unchanged.Docs/Contributing/AddingNode.csnow tells a new node to callDerivativeOverfor its parts. Binder variables (#984, #993) are unaffected.The integrator relied on the spurious conditions in four places, which are now explicit:
SolveByEulerSubstitution's perfect-square test asked a value and missed symbolic squares such as(2 a b)^2 - 4 b^2 a^2. It now asksIsAPerfectSquareDiscriminant.provided not a = 0. It is now declined explicitly; taken,acos(a + b x)/x^4ran past the budget.SolveByPartialFractions' logarithmic-derivative test (MayBeAConstantMultiple);SolveBySubstitution, which repeats at −x;KeepsTheVariableThroughEveryRewriting).Without them, 6.7.1:897 went from 4.1 GB to 20.8 GB; with them it is 0.38 GB.
Answers that change:
1/(x sqrt(k^2 x^2 + 2 k x + 1)): no value anywhere on master, declined by 2.5.0; now answered by the perfect-square rule, 832 characters.1/(x (a^2 + 2 a b x^3 + b^2 x^6)^(5/2))(Rubi's 1.2.3.2:131): answered on master in 1,039 characters with no value at any sample point; now declined, as 2.5.0 declined it.Chain against master a567c8b, with the harness at its current revision on both arms:
Integrateitself where master neededSimplifyafterwards;All four answers are identical to master's.
Tests:
DerivativeTest.InnerSimplifyTest.PiecewiseDerivative2*tests now expectpiecewise(0 provided True), which simplifies to0. Their oldnot x^2 = 0was the quotient rule's denominator for a1/xthat does not vary in y, and their own comment said it "does not collapse all the way to 0".InverseTangentPowerByPartsTest.ANonElementaryRemainderIsDeclinedQuickly;SlowDeclinesAheadOfTheAnsweringRuleIntegralTestcases.All three pass alone. Those two rows allocate the same on master (7.65 and 3.93 GB) and this branch (7.65 and 3.90 GB), with identical answers.
The BREAKING-CHANGES.md entry has 2.5.0's column measured. It also rewords one sentence of the
acsch(c x)entry, which said a node with a rule of its own keeps it, which is no longer true.🤖 Generated with Claude Code
https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura