Reputation: 1365
The first function in the code below uses double integration with scipy.integrate.dblquad
to calculate the differential entropy, c*np.log(c)
, of a copula density function c
, which has one dependence parameter, theta
, usually positive.
The second function in the code below tries to solve the same problem as above, but using the multiple integral solver scipy.integrate.nquad
from scipy import integrate
import numpy as np
def dblquad_(theta):
"Double integration"
c = lambda v, u: ((1+theta)*(u*v)**(-1-theta)) * (u**(-theta)+v**(-theta)-1)**(-1/theta-2)
return -integrate.dblquad(
lambda u,v: c(v,u)*np.log(c(v,u)),
0, 1, lambda u: 0, lambda u: 1
)[0]
def nquad_(n,theta):
"Multiple integration"
c = lambda *us: ((1+theta)*np.prod(us)**(-1-theta)) * (np.sum(np.power(us,-theta))-1)**(-1/theta-2)
return -integrate.nquad(
func = lambda *us : c(*us)*np.log(c(*us)),
ranges = [(0,1) for i in range(n)],
args = (theta,)
)[0]
n=2
theta = 1
print(dblquad_(theta))
print(nquad_(n,theta))
The dblquad
-based function gives an answer of -0.7127
, while the nquad
gives -0.5823
and noticeably takes longer. Why are the solutions different even though I have set both to solve an n=2
-dimensional problem?
Upvotes: 1
Views: 688
Reputation: 4588
With the values of n
and theta
you provided, the output of your code is:
-0.1931471805597395
0.17055845832017144,
not -0.7127
and -0.5823
.
The first value (-0.1931471805597395
) is the correct one (you can check it here for yourself).
The problem in nquad_
lies with the handling of the theta
parameter. Thanks @mikuszefski for providing the explanation; I copy it here for clarity:
nquad
passeslambda
to the function as required. The lambda is programmed in such a way that it accepts arbitrary number of arguments, so it happily takes it and puts it in the list of powers and sums. Hence you do not get, e.g.1/u**t+1/v**t -1
but1/u**t+1/v**t + 1/t**t -1
. The function call just does not match the intended function use. If you instead would writeus[0]**() + us[1]**() - 1
it works.
Here is the modified code:
from scipy import integrate
import numpy as np
def dblquad_(theta):
"Double integration"
c = lambda v, u: ((1+theta)*(u*v)**(-1-theta)) * (u**(-theta)+v**(-theta)-1)**(-1/theta-2)
return -integrate.dblquad(
lambda u,v: c(v,u)*np.log(c(v,u)),
0, 1, lambda u: 0, lambda u: 1
)[0]
def nquad_(n,theta):
"Multiple integration"
c = lambda *us: ((1+theta)*np.prod((us[0], us[1]))**(-1-theta)) * (np.sum(np.power((us[0], us[1]),-theta))-1)**(-1/theta-2)
return -integrate.nquad(
func = lambda *us : c(*us)*np.log(c(*us)),
ranges = [(0,1) for i in range(n)],
args=(theta,)
)[0]
n=2
theta = 1
print(dblquad_(theta))
print(nquad_(n,theta))
Output:
-0.1931471805597395
-0.1931471805597395
Upvotes: 2