Skip to content

Conversation

eagleoflqj
Copy link
Member

References to other Issues or PRs

This justifies #23566
Wolfram Alpha result: https://www.wolframalpha.com/input?i=arccosh%28x%29+derivative

Brief description of what is fixed or changed

Other comments

Release Notes

  • functions
    • Fix derivative of acosh

@eagleoflqj eagleoflqj requested a review from oscarbenjamin June 2, 2022 05:05
@sympy-bot
Copy link

sympy-bot commented Jun 2, 2022

Hi, I am the SymPy bot (v167). I'm here to help you write a release notes entry. Please read the guide on how to write release notes.

Your release notes are in good order.

Here is what the release notes will look like:

This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.11.

Click here to see the pull request description that was parsed.
<!-- Your title above should be a short description of what
was changed. Do not include the issue number in the title. -->

#### References to other Issues or PRs
<!-- If this pull request fixes an issue, write "Fixes #NNNN" in that exact
format, e.g. "Fixes #1234" (see
https://tinyurl.com/auto-closing for more information). Also, please
write a comment on that issue linking back to this pull request once it is
open. -->

This justifies #23566
Wolfram Alpha result: https://www.wolframalpha.com/input?i=arccosh%28x%29+derivative
#### Brief description of what is fixed or changed


#### Other comments


#### Release Notes

<!-- Write the release notes for this release below between the BEGIN and END
statements. The basic format is a bulleted list with the name of the subpackage
and the release note for this PR. For example:

* solvers
  * Added a new solver for logarithmic equations.

* functions
  * Fixed a bug with log of integers.

or if no release note(s) should be included use:

NO ENTRY

See https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more
information on how to write release notes. The bot will check your release
notes automatically to see if they are formatted correctly. -->

<!-- BEGIN RELEASE NOTES -->
* functions
  * Fix derivative of acosh
<!-- END RELEASE NOTES -->

Update

The release notes on the wiki have been updated.

@anutosh491
Copy link
Member

Change looks good to me but failing test need to be looked into !

@asmeurer
Copy link
Member

asmeurer commented Jun 2, 2022

The failing tests are because changing the output of diff affects the heurisch algorithm. According to the linked issue, it's not clear if the failing integrals were even correct before.

@oscarbenjamin
Copy link
Collaborator

DLMF (https://dlmf.nist.gov/4.38) gives the derivative as

d/dz arccosh(z) = +- 1/sqrt(z**2 - 1)

where the +- depends on whether z is in the left or right side of the complex plane.

Is that equivalent to 1/(sqrt(z-1)*sqrt(z+1))?

That seems to agree in all quadrants:

In [59]: e1 = sign(re(z))/sqrt(z**2 - 1)

In [60]: e2 = 1/(sqrt(z-1)*sqrt(z+1))

In [61]: e1
Out[61]: 
sign(re(z))
───────────
   ________2     
╲╱  z  - 1 

In [62]: e2
Out[62]: 
         1         
───────────────────
  _______   _______
╲╱ z - 1 ⋅╲╱ z + 1 

In [63]: (e1 - e2).subs(z, 1+I).n()
Out[63]: -0.e-124 + 0.e-124

In [64]: (e1 - e2).subs(z, 1-I).n()
Out[64]: -0.e-124 - 0.e-124

In [65]: (e1 - e2).subs(z, -1+I).n()
Out[65]: -0.e-134 - 0.e-134

In [66]: (e1 - e2).subs(z, -1-I).n()
Out[66]: -0.e-128 + 0.e-125

The formulas are perhaps consistent on the imaginary axis if + is taken on the positive axis and - on the negative imaginary axis:

In [83]: e1 = +1/sqrt(z**2 - 1)

In [84]: e2 = 1/(sqrt(z-1)*sqrt(z+1))

In [85]: e1.subs(z, I).n()
Out[85]: -0.707106781186548

In [86]: e2.subs(z, I).n()
Out[86]: -0.707106781186548

In [87]: e1.subs(z, -I).n()
Out[87]: -0.707106781186548

In [88]: e2.subs(z, -I).n()
Out[88]: 0.707106781186548

At +-0.5 the formulas seem to contradict:

In [93]: e1 = sign(re(z))/sqrt(z**2 - 1)

In [94]: e2 = 1/(sqrt(z-1)*sqrt(z+1))

In [95]: e1.subs(z, 0.5).n()
Out[95]: -1.15470053837925

In [96]: e2.subs(z, 0.5).n()
Out[96]: -1.15470053837925

In [97]: e1.subs(z, -0.5).n()
Out[97]: 1.15470053837925

In [98]: e2.subs(z, -0.5).n()
Out[98]: -1.15470053837925

At least for mpmath's numerical evaluation it seems that the new formula in this PR (e2) agrees with the numerical derivative at +-0.5 and +-I:

In [99]: x = -0.5

In [100]: h = 0.0001

In [101]: N((acosh(x+h) - acosh(x))/h)
Out[101]: -1.15466205349524

In [102]: x = I

In [103]: N((acosh(x+h) - acosh(x))/h)
Out[103]: 1.7677669020512e-5 - 0.707106780890414

In [104]: x = -I

In [105]: N((acosh(x+h) - acosh(x))/h)
Out[105]: 1.7677669020512e-5 + 0.707106780890414

From a casual check this looks good but it would be good to do some serious consistency checking.

Looks like the result for acsch is already the same expression as wolfram rather than the one given in DLMF:

In [6]: acsch(z).diff(z)
Out[6]: 
      -1        
────────────────
        ________
 21  
z ⋅   ╱  1 + ── 
     ╱        2 
   ╲╱        z  

Maybe there should be some tests that randomly substitute values into different functions to check whether the numerical derivative agrees with the symbolic derivative at least under evaluation by mpmath. I expect that a bunch of bugs could be found like this one if all functions were tested.

@oscarbenjamin
Copy link
Collaborator

This justifies #23566

It would be good to have a test for the integral in the issue as well.

@jksuom
Copy link
Member

jksuom commented Jun 2, 2022

it seems that the definition given in wikipedia for complex arguments will agree with the title. It has the proper branch cut (-oo, 1).

@eagleoflqj eagleoflqj marked this pull request as draft June 3, 2022 01:54
@eagleoflqj eagleoflqj force-pushed the acosh_diff branch 2 times, most recently from d22969e to 70abd70 Compare June 18, 2022 01:59
@eagleoflqj eagleoflqj marked this pull request as ready for review June 18, 2022 03:15
@github-actions
Copy link

github-actions bot commented Jun 18, 2022

Benchmark results from GitHub Actions

Lower numbers are good, higher numbers are bad. A ratio less than 1
means a speed up and greater than 1 means a slowdown. Green lines
beginning with + are slowdowns (the PR is slower then master or
master is slower than the previous release). Red lines beginning
with - are speedups.

Significantly changed benchmark results (PR vs master)

Significantly changed benchmark results (master vs previous release)

       before           after         ratio
     [77f1d79c]       [d0134b30]
     <sympy-1.10.1^0>                 
+         124±2ms          233±5ms     1.89  sum.TimeSum.time_doit

Full benchmark results can be found as artifacts in GitHub Actions
(click on checks at the top of the PR).

@eagleoflqj
Copy link
Member Author

Failed (wrong) tests are corrected in other PRs, and integrate(1/sqrt(x**2-1)) == log(x + sqrt(x**2 - 1)) now.
I think this can be merged.

@@ -1102,7 +1102,8 @@ def test_derivs():
assert sech(x).diff(x) == -tanh(x)*sech(x)
assert acoth(x).diff(x) == 1/(-x**2 + 1)
assert asinh(x).diff(x) == 1/sqrt(x**2 + 1)
assert acosh(x).diff(x) == 1/sqrt(x**2 - 1)
assert acosh(x).diff(x) == 1/(sqrt(x - 1)*sqrt(x + 1))
assert acosh(x).diff(x) == acosh(x).rewrite(log).diff(x).simplify()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't use simplify in test code. Instead a more targeted simplification function should be used e.g. in this case together is sufficient.

@eagleoflqj eagleoflqj merged commit 4805b8d into sympy:master Jun 18, 2022
@eagleoflqj eagleoflqj deleted the acosh_diff branch June 18, 2022 15:30
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.

6 participants