Skip to content

An exponential times a rational function by Liouville's ansatz, the Hermite reduction first for a repeated factor, and a cache that had been remembering a scoped decline - #1287

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
exponential-ansatz
Sep 11, 2026
Merged

An exponential times a rational function by Liouville's ansatz, the Hermite reduction first for a repeated factor, and a cache that had been remembering a scoped decline#1287
Rafael-SOWNet merged 1 commit into
masterfrom
exponential-ansatz

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

e^x x/(1 + x)^2 is (e^x/(1 + x))'. e^(x^2)(1 + 2x^2) is (x e^(x^2))'.
(4x^5 - 1)/(1 + x + x^5)^2 is (-x/(1 + x + x^5))'. None had an antiderivative:
the first two are not a polynomial times an exponential, which is the shape by parts
reads, and the third has a denominator nothing factors.

The ansatz

Liouville's theorem says the elementary antiderivative of e^h R, with h and R
rational, is e^h times a rational function where it exists at all. So the rule
writes F = e^h N/D, with D read off the denominator of R -- every written power
lowered by one, then the denominator itself, and every level of a single written
power, since with an exponential in front the antiderivative's denominator need not
be one below the integrand's (e^(1/x)(1 + x)/x^4 has x^2 under it) -- and N a
polynomial of unknown coefficients. F' = e^h R is then a polynomial identity linear
in those coefficients, solved by the elimination the symbolic partial-fraction split
uses and checked at sampled points with every symbol pinned before anything is
returned
. An ansatz that finds no N has, by Liouville, shown there is no
elementary antiderivative of that shape: e^x/x, e^(x^2) and e^x/(1 + x) are
declined in a millisecond each, and a test pins that they stay declined.

A sum whose terms share one exponential is read whole: e^(x^2) + 2x^2 e^(x^2) is
(x e^(x^2))', and neither term is elementary on its own, so splitting it first --
which linearity does -- loses it.

The identity is built one column at a time as a numeric polynomial rather than
once with the unknowns in it. With fourteen unknowns over a degree-eleven denominator
the single symbolic expansion did not return; the fourteen numeric ones take a moment.

The Hermite reduction, and first

With no exponential the same ansatz is the rational part of the Hermite reduction,
and the full form is taken: R = (N/D)' + M/D_1, with D_1 the product of the
distinct factors and M a second unknown polynomial, so that a logarithmic part
beside the rational one does not defeat it. (1 + x^2 + x^4)/((1 + x^2)(4 + x^2)^2)
has both. What is left, M/D_1, is a proper fraction over a squarefree denominator,
and it is handed to the splits and not to the whole integrator: handing it to the
whole integrator sent one such remainder through every substitution and by-parts
attempt there is, thirty seconds to decline what the splits decline in milliseconds.

A denominator with a written repeated factor takes this first, ahead of the
coprime split and the root peeling. (1 + x^2)/(x (1 + x^3)^2) reached the same
answer through those after seventeen seconds of peeling and re-factoring; this way
it is under a tenth of one. x^7, (x^3 + 2)^2 and (1 + x^4)^3 are the same story.

Integration by parts with neither factor worth differentiating

The classic "neither is a polynomial, try both orderings" case of by parts ran on any
product. Once the Hermite reduction answered ∫u for a small rational piece of a
radical trigonometric integrand, by parts carried on with v' ∫u, three hundred
nodes of mixed arguments against forty, and every substitution below was tried on it:
thirty seconds to decline where it had taken a tenth of one. The case now runs only
with a factor worth differentiating -- a logarithm or an inverse function, whose
derivative is algebraic, or an exponential, whose integral is itself and which the
cyclic cases need. Measured on the Rubi sample with the restriction and without: the
same answers, eight seconds less.

The cache

That restriction surfaced a defect that by parts had been hiding. Five rules answer
only the question asked (#1265) and decline the same integrand one level down, and
the integrator's cache held such a null without the scope it was made in.
cos(x)^(-3), tried inside the search for 1/cos(x)^3 and declined there by the
scoped secant reduction, was then declined from the cache in two milliseconds when
asked for directly -- unseen until now because by parts used to answer it at depth
two regardless. The key carries the scope; a lookup takes a decline only from its own
scope and an answer from either, since an antiderivative that was found is right
wherever it is asked for. A test asks the two integrals in that order.

Measured

Every answer differentiated back, with parameters pinned.

Rubi corpus, 463-problem sample, against the master it was cut from (#1286), both
timed on the same evening:

master      300/463, 0 wrong, 0 timeouts, 102 s
with this   312/463, 0 wrong, 0 timeouts,  76 s

Twelve more and nothing lost: e^x x/(1 + x)^2, e^(x^2)(1 + 2x^2) twice and once as
a sum (Moses), e^(1/x)(1 + x)/x^4 (Hearn), Hebisch's e^(1/(x^2 - 1)) times a
rational function, (4x^5 - 1)/(1 + x + x^5)^2 (Apostol), Stewart's
(1 + x^2 + x^4)/((1 + x^2)(4 + x^2)^2), Timofeev's x^5/(1 + x^4)^3 and
(1 + x^2)/(x (1 + x^3)^2), and two the reduction reached on its own:
ln(x)/(1 + ln(x))^2 and (3x - 1)^(4/3)/x^2. The sum of per-problem time over the
sample is 100 s to 75 s.

Two pinned declines moved as their tests said they would:
BinomialDenominatorIntegralTest had 1/(x^3 + 2)^2 as outside the binomial rule's
shape, and it is the reduction's first and then the rule's;
ExpandedPowerIntegralTest had (a - b x^2)^3/x^7 as unreached, and x^7 is a power
of a linear.

The five test suites are green.

Part of #718.

🤖 Generated with Claude Code

https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

…ermite reduction first for a repeated factor, and a cache that had been remembering a scoped decline

`e^x x/(1 + x)^2` is `(e^x/(1 + x))'`. `e^(x^2)(1 + 2x^2)` is `(x e^(x^2))'`.
`(4x^5 - 1)/(1 + x + x^5)^2` is `(-x/(1 + x + x^5))'`. None had an antiderivative:
the first two are not a polynomial times an exponential, which is the shape by parts
reads, and the third has a denominator nothing factors.

## The ansatz

Liouville's theorem says the elementary antiderivative of `e^h R`, with `h` and `R`
rational, is `e^h` times a rational function where it exists at all. So the rule
writes `F = e^h N/D`, with `D` read off the denominator of `R` -- every written power
lowered by one, then the denominator itself, and every level of a single written
power, since with an exponential in front the antiderivative's denominator need not
be one below the integrand's (`e^(1/x)(1 + x)/x^4` has `x^2` under it) -- and `N` a
polynomial of unknown coefficients. `F' = e^h R` is then a polynomial identity linear
in those coefficients, solved by the elimination the symbolic partial-fraction split
uses and **checked at sampled points with every symbol pinned before anything is
returned**. An ansatz that finds no `N` has, by Liouville, shown there is no
elementary antiderivative of that shape: `e^x/x`, `e^(x^2)` and `e^x/(1 + x)` are
declined in a millisecond each, and a test pins that they stay declined.

A sum whose terms share one exponential is read whole: `e^(x^2) + 2x^2 e^(x^2)` is
`(x e^(x^2))'`, and neither term is elementary on its own, so splitting it first --
which linearity does -- loses it.

The identity is built **one column at a time** as a numeric polynomial rather than
once with the unknowns in it. With fourteen unknowns over a degree-eleven denominator
the single symbolic expansion did not return; the fourteen numeric ones take a moment.

## The Hermite reduction, and first

With no exponential the same ansatz is the rational part of the Hermite reduction,
and the full form is taken: `R = (N/D)' + M/D_1`, with `D_1` the product of the
distinct factors and `M` a second unknown polynomial, so that a logarithmic part
beside the rational one does not defeat it. `(1 + x^2 + x^4)/((1 + x^2)(4 + x^2)^2)`
has both. What is left, `M/D_1`, is a proper fraction over a squarefree denominator,
and it is handed to the splits and not to the whole integrator: handing it to the
whole integrator sent one such remainder through every substitution and by-parts
attempt there is, thirty seconds to decline what the splits decline in milliseconds.

A denominator with a written repeated factor takes this **first**, ahead of the
coprime split and the root peeling. `(1 + x^2)/(x (1 + x^3)^2)` reached the same
answer through those after seventeen seconds of peeling and re-factoring; this way
it is under a tenth of one. `x^7`, `(x^3 + 2)^2` and `(1 + x^4)^3` are the same story.

## Integration by parts with neither factor worth differentiating

The classic "neither is a polynomial, try both orderings" case of by parts ran on any
product. Once the Hermite reduction answered `∫u` for a small rational piece of a
radical trigonometric integrand, by parts carried on with `v' ∫u`, three hundred
nodes of mixed arguments against forty, and every substitution below was tried on it:
thirty seconds to decline where it had taken a tenth of one. The case now runs only
with a factor worth differentiating -- a logarithm or an inverse function, whose
derivative is algebraic, or an exponential, whose integral is itself and which the
cyclic cases need. Measured on the Rubi sample with the restriction and without: the
same answers, eight seconds less.

## The cache

That restriction surfaced a defect that by parts had been hiding. Five rules answer
only the question asked (#1265) and decline the same integrand one level down, and
the integrator's cache held such a `null` without the scope it was made in.
`cos(x)^(-3)`, tried inside the search for `1/cos(x)^3` and declined there by the
scoped secant reduction, was then declined *from the cache* in two milliseconds when
asked for directly -- unseen until now because by parts used to answer it at depth
two regardless. The key carries the scope; a lookup takes a decline only from its own
scope and an answer from either, since an antiderivative that was found is right
wherever it is asked for. A test asks the two integrals in that order.

## Measured

Every answer differentiated back, with parameters pinned.

Rubi corpus, 463-problem sample, against the master it was cut from (#1286), both
timed on the same evening:

    master      300/463, 0 wrong, 0 timeouts, 102 s
    with this   312/463, 0 wrong, 0 timeouts,  76 s

Twelve more and nothing lost: `e^x x/(1 + x)^2`, `e^(x^2)(1 + 2x^2)` twice and once as
a sum (Moses), `e^(1/x)(1 + x)/x^4` (Hearn), Hebisch's `e^(1/(x^2 - 1))` times a
rational function, `(4x^5 - 1)/(1 + x + x^5)^2` (Apostol), Stewart's
`(1 + x^2 + x^4)/((1 + x^2)(4 + x^2)^2)`, Timofeev's `x^5/(1 + x^4)^3` and
`(1 + x^2)/(x (1 + x^3)^2)`, and two the reduction reached on its own:
`ln(x)/(1 + ln(x))^2` and `(3x - 1)^(4/3)/x^2`. The sum of per-problem time over the
sample is 100 s to 75 s.

Two pinned declines moved as their tests said they would:
`BinomialDenominatorIntegralTest` had `1/(x^3 + 2)^2` as outside the binomial rule's
shape, and it is the reduction's first and then the rule's;
`ExpandedPowerIntegralTest` had `(a - b x^2)^3/x^7` as unreached, and `x^7` is a power
of a linear.

The five test suites are green.

Part of #718.

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 32be20d into master Sep 11, 2026
31 checks passed
@Rafael-SOWNet
Rafael-SOWNet deleted the exponential-ansatz branch September 11, 2026 18:10
Rafael-SOWNet added a commit that referenced this pull request Sep 11, 2026
…top-level sum asked at the top, and a bare inverse function by parts (#1288)

`sqrt(1 + x^3)/x` had no antiderivative. `x^2 sqrt(1 + x^3)` and `x^5 sqrt(1 + x^3)`
did, by the same substitution, and the rule for it (#1275) stopped where Chebyshev's
first case does.

## The second case, with a rational function left over

Under `u = (a + b x^n)^(1/q)`, with `s = (m + 1)/n`:

    int x^m (a + b x^n)^(p/q) dx = (q/(n b^s)) int u^(p+q-1) (u^q - a)^(s-1) du

which is a polynomial in `u` when `s >= 1` -- what the rule expanded -- and a
**rational function** of `u` when `s <= 0`, which it read as "not a polynomial" and
declined. `sqrt(1 + x^3)/x` is `(2/3) int u^2/(u^2 - 1) du`; `1/(x sqrt(1 - x^3))` is
`(2/3) int 1/(u^2 - 1) du`. The rational integrator answers those, and the rule now
hands them to it.

## The third case, through the reciprocal

Where `s + p/q` is whole instead, `x = 1/y` turns `x^m (a + b x^n)^(p/q) dx` into
`-y^m' (b + a y^n)^(p/q) dy` with `m' = -m - 2 - n p/q`, a whole number, and
`(m' + 1)/n = -(s + p/q)`, whole -- the second case in `y`, with `a` and `b`
exchanged, and `y = 1/x` put back afterwards. `x^6 (3 + 4x^4)^(1/4)` is
`-9 int u^4/(u^4 - 4)^3 du` that way, which is the Hermite reduction's (#1287) and
the binomial rule's. Chebyshev proved there is no fourth case, so a binomial
differential outside these two is declined for a reason.

## A term of a top-level sum is asked at the top

`(x^3 - 1)/(2 + x^3)^(1/3)` is two binomial differentials, and was declined although
each term alone is answered. Linearity splits the integrand before anything else,
and every term it produced sat one level down -- where the five rules scoped to the
question asked (#1265, #1280) decline. A term of a top-level sum is strictly smaller
than the sum and is not a continuation of any rule's search, which is what the
scope was measured to stop; it is asked at the top now. Only from the top: one level
down the terms stay one level down, as before. `sec(x)^3 + x` is the same story with
the secant reduction.

## A bare inverse function, by parts against 1

`arctan(x sqrt(1 - x^2))` had no antiderivative. It is one step of parts against `1`
-- `x f(g) - int x g' f'(g) dx`, with an algebraic remainder -- and that step was never
taken: the by-parts rule runs on a product, a single node is not one, and a linear
argument is the table's. The remainder is answered where the radical rules reach it,
which is three of Charlwood's and Bondarenko's `ln(1/x^4 + x^4)`; the rest of that
family wants an Euler substitution the library does not have, and declines in about a
second, which a test pins. Asked, not volunteered, like the regrouping beside it.

## Measured

Every answer differentiated back.

Rubi corpus, 463-problem sample, against #1287's branch it was cut from, both timed
on the same evening:

    #1287       312/463, 0 wrong, 0 timeouts, 76 s
    with this   325/463, 0 wrong, 0 timeouts, 80 s

Thirteen more and nothing lost: `arctan(x sqrt(1 - x^2))`, `arctan(x sqrt(1 + x^2))`
(Charlwood) and `ln(1/x^4 + x^4)` (Bondarenko) by parts against 1; and by the binomial
rule `sqrt(1 + x^3)/x` (Charlwood), `1/(x sqrt(1 - x^3))` and
`sqrt(1 + x^8)/(x (1 + x^8))` (Bronstein), `x^6 (3 + 4x^4)^(1/4)` and
`(x^3 - 1)/(2 + x^3)^(1/3)` (Timofeev), and five of Welz's: `(1 - x^3)^(1/3)/x`,
`(1 - x^3)^(2/3)/x`, `1/(x (1 - x^2)^(1/3))`, `1/(x (1 - x^2)^(2/3))`,
`1/(x (1 - x^3)^(1/3))`. The sum of per-problem time over the sample is 75 s to 79 s,
which is the answers.

`BinomialDifferentialTest.OutsideTheFirstCase` had `1/(x (1 + x^3)^(1/3))` as a case
that may be declined; it is the second case with `s = 0` and moved to the answered
theory, with the three that Chebyshev says have no antiderivative kept where they
were.

The five test suites are green.

Part of #718.


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