asc-community / asc-community/AngouriMath
A square root of a quadratic: Euler's substitutions work, cost one wrong answer and 3x the time
- Dominant language
- C#
- Stars
- 831
- Forks
- 79
- Avg merge
- 3h 23m
- Merged PRs (30d)
- 309
Description
A square root of a **quadratic** is the largest remaining gap in the integrator, and Euler's substitutions rationalise it. I implemented them, measured them, and **did not ship them**, because the measurement says they are not ready. Writing down what they cost so the next attempt starts from evidence rather than from scratch.
### The size of the prize
Classifying all 937 integrands the Rubi run leaves unanswered, by shape:
| class | count | share |
|---|--:|--:|
| radical / fractional power | 361 | **38.5%** |
| trigonometric | 185 | 19.7% |
| rational / algebraic | 112 | 12.0% |
| inverse trig / hyperbolic | 96 | 10.2% |
| exponential | 70 | 7.5% |
Radicals are the largest class by a wide margin. Within them, `sqrt(linear)` is 67 and is now answered by #1243. **216 involve a quadratic under a root** — 108 with a positive leading coefficient, 50 negative, 58 where the sign is not obvious from the text.
### What I implemented
Euler's substitutions, chosen over the textbook trigonometric one because they land on a *rational* integrand in one step rather than on a rational function of sine and cosine that then needs the half-angle substitution as well:
- **a > 0** — `t = sqrt(Q) - x sqrt(a)`, giving `x = (t^2 - c)/(b - 2 t sqrt(a))` and `sqrt(Q) = t + x sqrt(a)`.
- **a < 0** — the radicand is non-negative only between two real roots, so `Q = a(x - α)(x - β)` and `sqrt(Q) = t(x - α)` gives `x = (aβ - t^2 α)/(a - t^2)`, with the roots from the quadratic formula rather than a solver.
It works. `1/(1+x^2)^(3/2)`, `1/(1-x^2)^(3/2)` and `sqrt(x+x^2)/x` all came out and all differentiate back.
### What it cost, which is why it is not merged
| | before | with Euler |
|---|--:|--:|
| solved | 863 | 899 |
| **wrong** | **0** | **1** |
| timeouts | 12 | 43 |
| wall clock, whole corpus | ~650 s | **~1,900 s** |
Thirty-six more answers, and:
**One wrong answer**, and it is the bad kind. `x^4/(-x^2+sqrt(10))^(9/2)` comes back as `NaN + C`. `NaN` is a claim that the antiderivative does not exist; it does exist, and Rubi prints it. Declining would be true, so this is a wrong answer where a refusal was available. I added a guard rejecting an answer containing `NaN` and it did not catch this one — the `NaN` appears *after* the rule returns, in the inner simplification `Integrate` applies to the antiderivative, so a guard inside the rule is in the wrong place.
**Thirty-one problems that used to be answered now time out**, and the whole corpus takes about three times as long. A size bound on the rewritten integrand (400 nodes) did not move either number, so the cost is not a few huge cases — it is spread across everything the rule fires on.
### What the next attempt should do differently
1. **Guard where the NaN appears, not where it is produced.** Either check the fully simplified antiderivative, or — better — have the rule verify its own answer by differentiating back before returning it. The rule rewrites into a form whose correctness is easy to check and hard to reason about, which is exactly when a self-check earns its cost.
2. **Find where the time goes before widening the rule.** Three times the corpus is not a price worth paying for 36 problems, and the size bound says it is not the obvious cause. My guess, untested, is the `Simplify` on the rewritten integrand.
3. **Consider the trigonometric substitution for the shapes that have a tidy form**, and keep Euler for the rest. The answers Euler gives are correct and algebraic — `4/(2(sqrt(1+x^2) - x)^2 + 2)` where a textbook writes `x/sqrt(1+x^2)` — which is a fair trade for coverage but not for the shapes `IntegralPatterns` already answers.
The branch is not pushed; the code is reproducible from the description above, and I would rather rewrite it against a measurement than resurrect it.
Contributor guide
Research direction
Start by reproducing the Rubi corpus measurement and inspect the integration rule, the inner Simplify step, and the IntegralPatterns cases mentioned in the issue. A successful follow-up should prevent NaN results, verify returned antiderivatives by differentiating them, and avoid the reported timeouts and roughly threefold corpus slowdown.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100