New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
B(1) = +½ set 2: generalised Bernoulli function #23984
Conversation
In Peter Luschny's "An introduction to the Bernoulli function" (https://arxiv.org/abs/2009.06743, will just be called Luschny in future commits) a generalised (two-argument) Bernoulli function is defined. One of the given representations is ⎧ 1 for s = 0 B(s, a) = ⎨ ⎩-s⋅ζ(1 - s, a) otherwise When s is a nonnegative integer this function reproduces the Bernoulli polynomials; when in addition a = 1 (the default choice for the Hurwitz zeta function's second argument, yielding Riemann's zeta) the Bernoulli numbers are obtained. Hence B(1) = +1/2, which is how Jakob Bernoulli originally defined his numbers in Ars Conjectandi (1713); this choice gives the simpler form/wider range of validity than B(1) = -1/2 for very many equations like Faulhaber's formula and the Euler–Maclaurin summation formula. We use the zeta representation of the Bernoulli function, despite Luschny striving to avoid such dependence by defining it as an integral, since mpmath provides a correct implementation of the Hurwitz zeta function; SymPy's zeta() was also aligned to Hurwitz zeta in sympy#23973.
✅ 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.12. Click here to see the pull request description that was parsed.
Update The release notes on the wiki have been updated. |
Benchmark results from GitHub Actions Lower numbers are good, higher numbers are bad. A ratio less than 1 Significantly changed benchmark results (PR vs master) Significantly changed benchmark results (master vs previous release) before after ratio
[41d90958] [a3826118]
- 987±3μs 626±2μs 0.63 solve.TimeSparseSystem.time_linear_eq_to_matrix(10)
- 2.84±0.01ms 1.16±0ms 0.41 solve.TimeSparseSystem.time_linear_eq_to_matrix(20)
- 5.62±0.01ms 1.70±0ms 0.30 solve.TimeSparseSystem.time_linear_eq_to_matrix(30)
Full benchmark results can be found as artifacts in GitHub Actions |
I think this looks good. Does anyone else have any opinions about this? The discussion for the rationale for this change is in the linked issue and reference cited above. Not a new problem but this should also get fixed:
That's scipy's bernoulli function which is inconsistent with SymPy's. |
I think I've got the solution for that. Put the following code in def _print_bernoulli(self, expr):
return self._print(expr._eval_rewrite_as_zeta(*expr.args)) Does this make sense and should I commit it in this PR? |
I think that makes sense and could go into this. Possibly with a small comment of the type |
How surprising that it's a one-liner – but manipulating an expression in a printing module is very sneaky.
Okay let's get this in. Thanks @Parcly-Taxel! |
Luschny defines the generalised Genocchi function in terms of the generalised Bernoulli function (implemented in sympy#23984) as G(s, a) = 2^s (B(s, a/2) - B(s, (a+1) / 2)) which can be rather easily rewritten as G(s, a) = 2 (B(s, a) - 2^s B(s, (a+1) / 2)) which is the form used here. When s is a nonnegative integer this function reproduces the (so-called) Genocchi polynomials, which have integer coefficients; when in addition a = 1 the Genocchi numbers are obtained, with G(1) = -1. The second term in the rewritten expression (2^s B(s, (a+1)/2)) is what Luschny calls the central Bernoulli function, which reduces to the central Bernoulli numbers when a = 0.
The lambdified bernoulli was already wrong anyway. |
This is a very wrong move and should be undone. You have been tricked to do that by people with no authority whatsoever. This is not good to try changing the stable convention used by the large majority of mathematical papers. |
You have no authority here to decide what |
@Parcly-Taxel, I think you have just agreed that you tricked them:
|
It's not too late to revert anything. Nothing has been released yet. |
There was no trickery involved here. There is also no authority defining what the Bernoulli numbers are, just as there is no authority defining |
Can we please keep the discussions here civil and within our code of conduct. Keep the discussion to the technical merits and specific mathematical details. Claiming that people are "playing tricks", especially without any arguments to back it up, is not a helpful avenue of discussion and is unnecessarily antagonistic. Also, it would be best to have this discussion at #23866. There's a lot of PRs relating to this issue in SymPy, but that's the main issue for As Oscar stated, this is not yet "locked in", because it hasn't been in a release. That was done on purpose because we knew this could be controversial. |
References to other Issues or PRs
Part 2 of the changes formerly included in #23926, building upon #23973. The changes here are also the actual changes that will fix #23866.
Brief description of what is fixed or changed
This PR generalises
bernoulli()
to the generalised Bernoulli function described in Peter Luschny's "An introduction to the Bernoulli function":$$B(s,a)=\begin{cases}1&s=0\\-s\zeta(1-s,a)&s\ne0\end{cases}$$
In the process it also changes
bernoulli(1)
to+1/2
.Other comments
Since the Genocchi numbers are currently defined in terms of the Bernoulli numbers, this also changes
genocchi(1)
to-1
; a later PR will generalise this integer sequence to the two-complex-argument generalised Genocchi function in the same vein as the generalised Bernoulli function, though.Luschny also defines the central Bernoulli numbers and polynomials, but I have not made a new SymPy function out of that because its generalisation to arbitrary complex arguments can be expressed as$2^s B(s,\frac{a+1}2)$ .
Release Notes
bernoulli(1)
is now1/2
instead of-1/2
andgenocchi(1)
is now-1
instead of1
.bernoulli()
now accepts complex arguments, implementing Luschny (2020).