Interestingly, most methods provided by scipy.integrate
yields a number very close to pi
but less than pi
from k = 2
onwards. eg quad, fixed_quad, quadrature, romberg
. Even using the diffferent gaus quadratures in scipy.special.root_*
yields to a value less than pi
by k=2.
import numpy as np
import scipy
def fn(x, k, alpha, beta):
x = np.array(x).reshape(-1,1)
w = x / (beta * np.arange(1, k + 1) - (beta - 1)) ** alpha / np.pi
return np.sinc(w).prod(1)
scipy.integrate.quad(fn, -np.inf, np.inf, (5, 1, 2))
(3.1415926520655124, 4.664127099015817e-08)
This value is already less than pi
and k is only 5
so had to try other methods
In order to use the other methods, a vectorized function that is scaled to [-1,1] interval has to be defined:
def fn2(t, k, alpha, beta):
t = np.array(t).reshape(-1)
results = np.zeros_like(t)
index = np.abs(t) != 1
t_ = t[index]
denom = 1 - t_**2
x = (t_/denom).reshape(-1,1)
w = x / (beta * np.arange(1, k + 1) - (beta - 1)) ** alpha / np.pi
results[index] = np.sinc(w).prod(1)*(1 + t_ **2) / denom**2
return results
scipy.integrate.quadrature(fn2, -1,1,(10,1,2), maxiter=300, vec_func = True)
(3.1415900583875214, 3.7533582020188305e-08)
scipy.integrate.romberg(fn2, -1,1,(7,1,2), divmax = 20, vec_func = True)
array([3.14159266])
Still no success in the integration since the value is less than pi
for K=10
Lets try julia
:
## %%julia
using Pkg
using QuadGK
function fn(x, k, alpha, beta)
w = x ./(beta .* range(1, k) .- (beta - 1)).^alpha
x == 0 ? 1. : prod(sin.(w)./w)
end
quadgk(x -> fn(x, 5, 1., 2.), -Inf, Inf)
(3.1415926432027703, 4.3290522541976784e-8)
Also no success. since value is less than pi
for k = 5
Mathematica?
beta = 2;
alpha = 1;
For[k = 2, k<10, k++,
Print["k=", k, " ", Integrate[Product[Sinc[x/(beta*i - beta+1)^alpha],{i,1,k}], {x, -Infinity, Infinity}]<Pi]]
Results:
k=1 False
k=2 False
k=3 False
k=4 False
k=5 False
k=6 False
k=7 False
k=8 True
k=9 True
So, Mathematica says that at k=8
the result is already less than pi.
What about R?
## %%R
fn <- function(x, k, alpha, beta){
a <- (beta * seq_len(k) - beta + 1)**alpha
ifelse(x==0, 1, apply(sin(w <- outer(x, a, '/'))/w, 1, prod))
}
integrate(fn, -Inf, Inf, k=10, alpha=1,beta=2)
3.141601 with absolute error < 0.00012
This seems to be successful. Compute for K such that the integral is less than pi.
##%%R
g <- function(k) {
integrate(fn, -Inf, Inf, k=k, alpha=1,beta=2)$value - pi
}
uniroot(g, c(3,20))
$root
[1] 14.99996
$f.root
[1] 1.430762e-07
$iter
[1] 19
$init.it
[1] NA
$estim.prec
[1] 6.103516e-05
R gives the root as 15
. You can use minimize/optim
and both methods returns 15
.
Since R uses Gauss-kronrod quadrature nodes and values, there should be a python implementation for that. but could not find any.
next try fixed_quad
playing around with n
. n = 200
seems to match the results from R:
scipy.integrate.fixed_quad(fn2, -1,1,(10,1,2), 200)
(3.141602220677316, None)
g = lambda k : scipy.integrate.fixed_quad(fn2, -1,1,(int(k),1,2), n = 200)[0] - np.pi
scipy.optimize.root_scalar(g, bracket=(4, 20))
converged: True
flag: converged
function_calls: 53
iterations: 52
root: 15.000000000000028
Notice that the root = 15
. Wow but that is trial and error with regards to the n, without which one cannot obtain the needed solution.
Other approximations?
nodes1, weights1 = scipy.special.roots_jacobi(1000,0,0)
fn2(nodes1,10,1,2)@weights1
3.1415923602907556
nodes2, weights2 = scipy.special.roots_legendre(1000)
fn2(nodes2,10,1,2)@weights2
3.1415923602907556
These values are still less than pi. So why Only R gives the results yet every other method fails?
Perhaps the author of that question used R. Every other approximation is close to pi, but mostly less than pi.
NB: I could not find the gauss-kronrod in python.
Conclusion: This is an ill-defined problem as the results of the integration need to be pi. thus an approximation could be smaller or larger than pi, and due to numerical approximations, different platforms would yield different results. eg the fixed_quad
method used above will yield different results for different n
. its not common to have a specific n that would yield the needed results. I had to optimize to find n=200
.