Repository navigation
Factor polynomials with whole roots (#177) - #669
Conversation
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #669 +/- ##
==========================================
- Coverage 80.99% 79.95% -1.05%
==========================================
Files 155 156 +1
Lines 13687 12602 -1085
Branches 1957 2055 +98
==========================================
- Hits 11086 10076 -1010
+ Misses 1990 1932 -58
+ Partials 611 594 -17 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| [Fact(Skip = "Integration returns a wrong antiderivative here on its own; " + | ||
| "it is right once the integration-recursion fix is also applied")] |
`x^2 + 2x + 1` stayed as it was written. Factoring it wants the rational root
theorem, which the library did not have.
A polynomial in one variable with rational coefficients now has its rational roots
found -- divisors of the constant term over divisors of the leading one, checked by
exact evaluation and divided out by exact synthetic division -- and the factored form
is handed to the simplifier as one more candidate. The simplifier keeps it alongside
the other forms and picks by its complexity metric, which is why `(1 + x)^2` wins
while `x^2 - 1` stays as it is.
Deliberately narrow, on two counts, both of which are load-bearing:
- Rational roots only. Factoring through every root would answer (x - i)(x + i)
for x^2 + 1 and (x - sqrt(2))(x + sqrt(2)) for x^2 - 2, which is not what anyone
means by factoring those.
- And only when the polynomial splits completely into whole roots. A partly
factored answer is not obviously better than the sum it came from, and
fractional roots turn up mostly in the output of calculus, where the expanded
form is the conventional one: the antiderivative of x^2 + x reads better as
x^3/3 + x^2/2 than as x^2 * (x + 3/2) / 3. Both of those were regressions in an
earlier draft of this that only required *a* root to be found.
On the corpus: 75 -> 76 solved and one fewer wrong answer.
Two existing tests change. BigSimple1 asserted the expanded form of (1 + x)^4 and
now gets (1 + x)^4, which is what it was asking for. FactorialXM1OverFactorialXM3
gets the same two factors in the other order.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The project multi-targets netstandard2.0 and net7.0, and the unit tests only build the latter, so two net7-only conveniences got through: KeyValuePair deconstruction and the range operator, which needs RuntimeHelpers.GetSubArray. The F# wrapper build is what caught them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Updated, and rebased onto current master. The skipped test is gone rather than updated. It only ever existed because this branch, on its own, perturbed #670 fixed the actual cause ( Suite is green on the rebase: 3841 passed, 0 failed. |
da2eb2e to
6453674
Compare
Closes #177:
x^2 + 2x + 1stayed as it was written.
A polynomial in one variable with rational coefficients has its rational roots found by
the rational root theorem — divisors of the constant term over divisors of the leading
one — each checked by exact evaluation and divided out by exact synthetic division. No
floating point is involved, so a root is either exact or not a root.
The factored form is handed to the simplifier as one more candidate, not as a
decision. It sits alongside the other forms already collected and the complexity metric
picks, which is why
(1 + x)^2wins whilex^2 - 1stays as it is.Deliberately narrow, on two counts
Both are load-bearing — an earlier draft that only required a root to be found
regressed real cases.
Rational roots only. Factoring through every root would answer
(x - i)(x + i)forx^2 + 1and(x - sqrt(2))(x + sqrt(2))forx^2 - 2, which is not what factoringthose means. Tests assert those are left alone.
And only when it splits completely into whole roots. A partly factored answer is not
obviously better than the sum it came from, and fractional roots turn up mostly in the
output of calculus, where the expanded form is the conventional one — the antiderivative
of
x^2 + xreads better asx^3/3 + x^2/2than asx^2 * (x + 3/2) / 3. That was areal regression in the earlier draft, and there is a test for it now.
Multivariate expressions are untouched and still go to the term-collecting rules.
Two existing tests change, and one is removed
BigSimple1asserted the expanded form of(1 + x)^4. It now gets(1 + x)^4,which is what it was asking for.
FactorialXM1OverFactorialXM3gets the same two factors in the other order.TestPowerSubstitution's second case is removed, because it was pinning a wronganswer:
That is not an antiderivative of the integrand. At
x = 2the integrand is 1200and the derivative of that answer is 1536. The true antiderivative is
(x³+2)³/3, which differentiates back exactly. I checked this on a stockmasterbuild — it is not caused by this PR; this PR only perturbs a wrong answer into a
differently wrong one, which is what surfaced it.
Rather than update the expectation to another wrong string, the case is restated as
what it should assert — that differentiating the answer returns the integrand — and
left
Skipped, matching how the other unfinished integration cases in that file arehandled. It is checked at points rather than symbolically, because the difference is
zero but
Simplifydoes not reduce it to zero.It passes once Fix two Simplify hangs, an integration stack overflow, and incomplete factoring (#403, #531, #178, #205) #665 is also applied. I bisected this: neither Fix two Simplify hangs, an integration stack overflow, and incomplete factoring (#403, #531, #178, #205) #665 nor this PR
fixes it alone, but together they do — with factoring available, the
Simplify(1)inside the integrator produces a form that lets u-substitution succeed, so the
integrand takes the correct route instead of the faulty by-parts one. The by-parts
defect is presumably still there, just no longer reached for this integrand. Once
both land, the skip can come off.
Testing
UnitTests3675 passed / 0 failed. On the 117-problem corpus this branch is 76 solvedagainst
master's 75, with one fewer wrong answer.18 new tests: the factored cases, value preservation for each (including the ones that
deliberately do not factor), the irrational and complex cases being left alone, the
partial-split case, the antiderivative case, and the multivariate case.
Independent of #663 through #668; touches no file any of them touch.
🤖 Generated with Claude Code