Let a numeric factor reach the coefficient when collecting like terms - #862
Merged
Conversation
CollectLikeTerms failed on the expression its own documentation cites: (x+1)^2 * (x+1)^2 came back as 1 + 4x + 2x^2 + 4x^2 + 4x^3 + x^4, with the two x^2 terms side by side instead of added. Instrumenting the monomial keys gives the cause in one line: term=(2 * x) ^ 2 key='4 * x ^ 2^1' coeff=1 (2 * x)^2 reduces to 4 * x^2, which is a product and not a power, so it fell to the exponent-of-one branch and the 4 was baked into the monomial key rather than extracted into the coefficient. Keyed on "4 * x ^ 2" it could never meet the plain x^2 terms. A factor that reduces to a product is now split again, and an integer power of a product is distributed over its factors, so the number reaches the coefficient in both shapes. Only for polynomial-shaped factors. Opening a product is what lets like terms meet and it is also what stops a product cancelling as a whole: lifting the 1/2 out of (1/2 * sin(2t))^2 * csc(t)^2 costs the cancellation to cos(t)^2, and DoubleAngleOverSineTest is there to catch exactly that. Collection is a statement about polynomials, so it opens polynomials and leaves anything carrying a function to the rules that know it. Two other shapes were tried and rejected against that test rather than against reasoning: splitting only products that carry a number does not help, since 1/2 is one; and comparing the collected and expanded forms by their complexity cannot work, because the payoff of leaving a product intact only appears after passes that run later -- which is what the comment on TheReportersSecondExpressionIsAlsoZero already says about this metric. Closes #855. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Closes #855.
The defect
CollectLikeTermsfailed on the expression its own documentation cites as the reason it exists:The two
x^2terms sit side by side instead of being added. Correct, but one term longer than it should be — and(x+1)^4,(x+1)*(x+1)*(x+1)*(x+1)and(x+1)^2*(x+2)^2all collect properly, which is what made it look arbitrary.The cause, from instrumenting the monomial keys
(2 * x)^2reduces to4 * x^2, which is a product, not a power, so it fell to the exponent-of-one branch and the4was baked into the monomial key instead of being extracted into the coefficient. Keyed on4 * x ^ 2, it could never meet the plainx^2terms.The fix
A factor that reduces to a product is split again, and an integer power of a product is distributed over its factors — so the number reaches the coefficient in both shapes.
(a*b)^n = a^n * b^nis used only for integern, where it holds for everyaandb.Only for polynomial-shaped factors, and that restriction is the whole design, not a caveat.
What the restriction is for
Opening a product is what lets like terms meet. It is also what stops a product cancelling as a whole:
DoubleAngleOverSineTest.TheReportersSecondExpressionIsAlsoZeroexists to catch exactly that, and it caught it. Collection is a statement about polynomials, so it now opens polynomials and leaves anything carrying a function to the rules that know it.Two other shapes tried and rejected — against the test, not against reasoning
1/2is a number, so the trigonometric term is opened anyway.SimplifiedRate. Does not work either, and the reason is already written down in this repository — the comment onTheReportersSecondExpressionIsAlsoZerosays the opened form "was offered to the complexity metric in the one shape where its payoff had not happened yet". A local comparison cannot see a payoff that only materialises after later passes. I tried it at theSimplificatorlevel too, offering the uncollected expansion as a candidate; still no.Recording these because each looks obviously right until it is run.
Measured
(x+1)^2 * (x+1)^21 + 4x + 2x² + 4x² + 4x³ + x⁴1 + 4x + 6x² + 4x³ + x⁴(x+y)^2 * (x+y)^2… + 2x²y² + (2xy)² + …… + 6x²y² + …(2x+1)^2 * (2x+1)^21 + 8x + 24x² + 32x³ + 16x⁴(3x)^2 + x^210x²(x*y+1)^2 * (x*y+1)^21 + 4xy + 6x²y² + 4x³y³ + x⁴y⁴All binomial coefficients
1, 4, 6, 4, 1as they should be.Six new cases, including one that asserts the trigonometric term is not opened — so the restriction has a test of its own rather than only the pre-existing one it was derived from.
🤖 Generated with Claude Code