Skip to content

A rational function of the hyperbolic tangent with a symbol among its coefficients is integrated by u = tanh(y) with the written factors kept, and an answer assembled from a decomposition with symbols is checked before it is given - #1377

Merged
Rafael-SOWNet merged 3 commits into
masterfrom
hyperbolic-tangent-rational
Sep 17, 2026

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

Rubi's hyperbolic families (family 6) with a symbol among the coefficients: 278 → 301 of the 417-problem sample, 0 wrong, 0 error, timeouts 57 → 47. The independent suites stay at 1707/1774, 0 wrong, 0 timeouts (1706 on master; the same set, ±2 s over 85 s).

Carries #1374's commit until that merges — this branch is cut from complex-division, because the sample was measured with the division fix in (a right antiderivative's derivative read as wrong at one point without it). Once #1374 is in, I rebase and the diff is the one commit.

What it does

A rational function of the hyperbolic tangent is integrated by u = tanh(y) with the written factors kept. Under u = e^x, Rubi's 1/(a + b coth(c + d x)^2)^2 is a rational function of the symbolic palindromic quartic (a + b) u^4 + 2(b − a) u^2 + (a + b) squared, whose roots are what the budget went on: 57 of the 417 timed out, most of them the tangent, cotangent, secant and cosecant families with a symbolic a + b f^2. Under u = tanh(y) it is u^4/((b + a u^2)^2 (1 − u^2)), which the symbolic partial fractions answer. SolveARationalFunctionOfTheHyperbolicTangent sits before the substitution search, which with a symbolic slope spent the whole budget on u = c + d x and never came back to the chain.

The rewrite keeps the written factors rather than expanding: every exponential is e^(k y) for one linear form y (the gather is shared with the tangent substitution for radicands of both signs, which now takes a linear argument too — the two routes ask for y at a different grain, see the commit); each maximal rational function of v = e^y among the factors, powers and radicands is read as v^m R(s) with s = v^2, homogenised on its own as Σ p_i (1 + u)^i (1 − u)^(d − i) over the same for the denominator, the common powers of 1 ± u divided out synthetically, the sides collected as polynomials over the symbols with the numeric content in front, and the powers of 1 + u, 1 − u, 1 − u^2 gathered into one each at the end. An integrand odd in v takes the half-angle u = tanh(y/2) only where every exponent is written with an even factor and there is no root; otherwise it is not this route's.

The exponential substitution takes the whole linear form. csch(29/10 + 13/10 x)^3 (17/10 + 23/10 sech(...)^2)^3 put u = e^(13/10 x) and left e^(29/10) in every coefficient, a quadratic the rational rules do not factor over — 110 s and no answer. Where every exponent is a multiple of one x + shift (cross-multiplied, so a symbolic slope is never divided by), u = e^(13/10 x + 29/10) and the coefficients are the numbers they were written with: 516 ms.

Two wrong answers and a crash found on the way, each guarded, each with an issue for the cause

#1369 1/((a + b x^2)^3 (x^2 − 1)) the Hermite ansatz's logarithmic part, coefficients that are quotients of 45th-degree polynomials in the symbols, decomposed correctly and integrated wrongly as a sum where each term is right alone. The Hermite branch checks its rest against the logarithmic part, and the written-factors branch its term-by-term integral, when a symbol is involved. The mixing itself is still open.
#1370 sqrt(a + b sech(x)) tanh(x)^5 integrated through i, a root of a negative radicand on the way; the tangent substitution checks its answer at sampled points when a symbol is involved.
#1373 csch(29/10 + 13/10 x)^3 (17/10 + 23/10 sech(...)^2)^3 stack overflow: the power-of-a-quadratic reduction recursed on a remainder the division had not reduced, a level a call. It declines a non-linear remainder now, in both places it is asked, and the case is a test.

The check the guards share, PartialFractions.DerivativeHoldsAtSampledPoints, pins the symbols before differentiating (sgn(f)' and |f|' want a real-valued f) and skips a point where the derivative cannot be evaluated rather than throwing out of the integrator.

Measured

Family 6, 20 problems a file, 5 s budget, master 54d8a30e against this branch:

Source Run master branch
6.1.1 (c+d x)^m (a+b sinh)^n 20 14 12
6.1.3 (e x)^m (a+b sinh(c+d x^n))^p 20 20 20
6.1.5 Hyperbolic sine functions 20 14 14
6.1.7 hyper^m (a+b sinh^n)^p 20 12 15
6.2.1 (c+d x)^m (a+b cosh)^n 20 13 13
6.2.2 (e x)^m (a+b x^n)^p cosh 20 20 20
6.2.3 (e x)^m (a+b cosh(c+d x^n))^p 19 19 19
6.2.5 Hyperbolic cosine functions 20 15 15
6.2.7 hyper^m (a+b cosh^n)^p 20 13 13
6.3.1 (c+d x)^m (a+b tanh)^n 10 10 10
6.3.2 Hyperbolic tangent functions 20 16 17
6.3.7 (d hyper)^m (a+b (c tanh)^n)^p 20 10 13
6.4.1 (c+d x)^m (a+b coth)^n 10 10 10
6.4.2 Hyperbolic cotangent functions 20 17 16
6.4.7 (d hyper)^m (a+b (c coth)^n)^p 20 4 6
6.5.1 (c+d x)^m (a+b sech)^n 4 1 1
6.5.2 (e x)^m (a+b sech(c+d x^n))^p 14 8 8
6.5.3 Hyperbolic secant functions 20 12 13
6.5.7 (d hyper)^m (a+b (c sech)^n)^p 20 9 15
6.6.1 (c+d x)^m (a+b csch)^n 7 3 3
6.6.2 (e x)^m (a+b csch(c+d x^n))^p 13 7 7
6.6.3 Hyperbolic cosecant functions 20 8 9
6.6.7 (d hyper)^m (a+b (c csch)^n)^p 20 8 15
6.7.1 Hyperbolic functions 20 15 17
total 417 278 301

26 gained, 4 lost: two at the edge of the budget (1/(b coth(c + d x)^4)^(2/3), csch(c + d x)^20 (a + b sinh(c + d x)^4)^3) which master answered in the corpus run from a warm memo at 5.2 s and 22 s of wall time and times out on alone at the same 5 s budget, exactly as this branch does — probed one process each on both builds; and two with i in the coefficients (cosh(c + d x)/(a + i a sinh(c + d x)), (c + d x)^2 (a + i a sinh(pe + f x))^2) that the harness now reports unverifiable on the reals rather than solved — a different answer form, not a wrong one. Every answer is verified by differentiating back with the parameters pinned, in the harness and in the library.

Four suites green (11366 / 134 / 18 / 41). No gate row is integration, and the change is confined to the integrator and one helper in PartialFractions.

Part of #718.

🤖 Generated with Claude Code

https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

Rafael-SOWNet and others added 2 commits September 16, 2026 06:40
…hich never forms the squared modulus

Complex division computed (a + ib)(c - id)/|c + id|^2 starting from
the reciprocal of the squared modulus, and for a divisor of 3 * 10^125
that is 10^-251, below the default context's exponent floor, so it
flushed to zero and the quotient came out 0 where it was 6 * 10^-7:
a right antiderivative's derivative -- csch(c+dx)^3 (a + b sech^2)^3,
whose quotient rule divides 2 * 10^119 by 3 * 10^125 at x = 5.71 --
read as wrong at that point. Any divisor beyond about 10^50 did the
same, and one below 10^-500 overflowed the square instead. Farther
than 10^40 from unit magnitude the division is Smith's method now,
which forms no square; nearer it is the route as it was, whose last
digits NumericDigits pins.

Four suites green (11,353 / 134 / 18 / 41).

Part of #1372.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
… coefficients is integrated by u = tanh(y) with the written factors kept, and an answer assembled from a decomposition with symbols is checked before it is given

Under u = e^x, Rubi's 1/(a + b coth(c + d x)^2)^2 is a rational
function of the symbolic palindromic quartic (a + b) u^4 + 2(b - a) u^2
+ (a + b) squared, whose roots are what the budget went on: fifty-seven
of the four hundred and seventeen problems of the hyperbolic sample
timed out, most of them the tangent, cotangent, secant and cosecant
families with a symbolic a + b f^2. Under u = tanh(y) it is
u^4/((b + a u^2)^2 (1 - u^2)), which the symbolic partial fractions
answer, and that is what SolveARationalFunctionOfTheHyperbolicTangent
does, before the substitution search, which with a symbolic slope
spent the whole budget on u = c + d x and never came back to the chain.

The rewrite keeps the written factors. Every exponential is e^(k y)
for one linear form y shared by all of them -- the gather is shared
with the tangent substitution for radicands of both signs, which now
takes a linear argument too, and the two routes ask for y at a
different grain: the substitution with the root keeps x itself where
the slope is whole, so that coth(x) is 1/u and not a quotient with the
root in it, and the rational route takes y as coarse as it comes, so
that coth(2x) is tanh(2x) and not a quartic in tanh(x). Each maximal
rational function of v = e^y among the factors, powers and radicands
is read as v^m R(s) with s = v^2 and m either 0 or 1, and homogenised
on its own, P(s)/Q(s) as the polynomials sum p_i (1 + u)^i (1 - u)^(d - i)
over the same for Q with the common powers of 1 - u and 1 + u divided
out synthetically, the sides collected as polynomials over the symbols
with the numeric content in front, and the powers of 1 + u, 1 - u and
1 - u^2 the pieces bring gathered into one each at the end. The
conjugate that the tangent substitution clears its root with squares
every degree and left this integrand a quotient of degree sixteen. An
integrand odd in v is not this route's, except where every exponent is
written with an even factor in front -- coth(c + d x) is written with
e^(2(c + d x)) -- and the integrand has no root, when the half of y is
the argument as written and u = tanh(c + d x); the half-angle for
sinh(x) answered what u = e^x answered in less.

On the way, two wrong answers and a crash, each with a guard here and
an issue for the cause. 1/((a + b x^2)^3 (x^2 - 1)) came back as a
piecewise with coefficients like 135 a^48 b^18 whose derivative was off
by 0.39 at pinned symbols: the Hermite ansatz's logarithmic part, with
coefficients that are uncancelled quotients of forty-fifth-degree
polynomials in the symbols, was decomposed over the written factors
correctly and integrated wrongly as a sum where each term is right on
its own. The Hermite branch checks its rest against the logarithmic
part now, and the written-factors branch its term-by-term integral
against the decomposition when a symbol is involved (#1369).
sqrt(a + b sech(x)) tanh(x)^5 was integrated through i, a root of a
negative radicand on the way, and the tangent substitution checks its
answer at sampled points where a symbol is involved (#1370). And
csch(29/10 + 13/10 x)^3 (17/10 + 23/10 sech(29/10 + 13/10 x)^2)^3 took
the process down: the power-of-a-quadratic reduction recursed on a
remainder the division had not reduced, a level a call; it declines a
remainder that is not linear now, in both places it is asked (#1373).
The check the guards share, DerivativeHoldsAtSampledPoints, pins the
symbols before differentiating -- sgn(f)' and |f|' want a real-valued
f -- and a point where a derivative cannot be evaluated is skipped
rather than thrown out of the integrator.

The crash's integrand, guarded, then took the budget ten times over:
the exponential substitution put u = e^(13/10 x) and left e^(29/10) in
every coefficient, a quadratic the rational rules do not factor over,
and each of the four terms cost seconds or was declined. Where every
exponent is a multiple of one x + shift -- cross-multiplied, so that a
symbolic slope is never divided by -- u is the base at the whole
linear form, e^(13/10 x + 29/10), and the coefficients are the numbers
they were written with: 516 ms. Rubi writes its arguments c + d x
throughout, so this is most of the numeric hyperbolic sample.

Hyperbolic sample (family 6, 20 a file): 278 -> 301 of 417, 0
wrong, 0 error. The independent suites: 1707/1774 (from 1706), 0
wrong, 0 timeouts.

Four suites green.

Part of #718.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
…on is integrated term by term and still checked at sampled points
@Rafael-SOWNet
Rafael-SOWNet merged commit a846738 into master Sep 17, 2026
31 checks passed
@Rafael-SOWNet
Rafael-SOWNet deleted the hyperbolic-tangent-rational branch September 17, 2026 13:34
Rafael-SOWNet added a commit that referenced this pull request Sep 18, 2026
…ponential substitution (#1410)

* A logarithm of a nested quotient is written over one bar under the exponential substitution

1/sqrt(atanh(tanh(a + b x))) was answered in 300 ms before the
exponential substitution took a symbolic slope (#1377) and not after.
atanh(tanh(a + b x)) arrives at the chain as
1/2 ln((1 + (w - 1)/(w + 1))/(1 - (w - 1)/(w + 1))) in w = e^(2(a + b x)),
and under u = w that logarithm is 1/2 ln(u); but the combining on the
way in reaches the quotient the integrand is and not one inside a
function, the simplifier combines nothing (#1239), and the substitution
search compared its candidates against the nested spelling and never
saw the u. Every logarithm whose argument is a rational function of u
with a quotient nested in it is now written over one bar in lowest
terms where that is smaller, before the integrand in u is asked.

Part of #718.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

* BREAKING-CHANGES: the logarithm of a nested quotient under the exponential substitution

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Rafael-SOWNet added a commit that referenced this pull request Oct 9, 2026
… 2.5.0

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
Rafael-SOWNet added a commit that referenced this pull request Oct 9, 2026
* Breaking-changes entries for #1828 to #1832 and #1374

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

* And for #1368, #1611 and #1517, each measured on 2.5.0

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

* And for #1289, #1312, #1315, #1377, #1380 and #1371, each measured on 2.5.0

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

---------

Co-authored-by: Claude Opus 5.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