Mam dwie zmienne losowe X i Y, które są równomiernie rozmieszczone na simplex: Oszacowanie gęstości prawdopodobieństwa sumy jednolitych zmiennych losowych w Pythonie
chcę oceniać gęstość ich sumy:
Po przeanalizowaniu powyższych integralną mój ostatecznym celem jest obliczenie następującej całki:
aby obliczyć th Pierwszą całką generuję równomiernie rozłożone punkty w simpleksie, a następnie sprawdzam, czy należą one do pożądanego regionu w powyższej całce i biorę ułamek punktów, aby ocenić powyższą gęstość.
Po obliczeniu powyższej gęstości postępuję w podobny sposób, aby obliczyć powyższy logarytm całkowy, aby obliczyć jego wartość. Jednak było to niezwykle nieefektywne i wymagało dużo czasu, na przykład 3-4 godzin. Czy ktoś może zaproponować mi skuteczny sposób rozwiązania tego w Pythonie? Używam pakietu Numpy.
Oto kod
import numpy as np
import math
import random
import numpy.random as nprnd
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
#This function checks if the point x lies the simplex and the negative simplex shifted by z
def InreqSumSimplex(x,z):
dim=len(x)
testShiftSimpl= all(z[i]-1 <= x[i] <= z[i] for i in range(0,dim)) and (sum(x) >= sum(z)-1)
return int(testShiftSimpl)
def InreqDiffSimplex(x,z):
dim=len(x)
testShiftSimpl= all(z[i] <= x[i] <= z[i]+1 for i in range(0,dim)) and (sum(x) <= sum(z)+1)
return int(testShiftSimpl)
#This is for the density X+Y
def DensityEvalSum(z,UniformCube):
dim=len(z)
Sum=0
for gen in UniformCube:
Exponential=[-math.log(i) for i in gen] #This is exponentially distributed
x=[i/sum(Exponential) for i in Exponential[0:dim]] #x is now uniformly distributed on simplex
Sum+=InreqSumSimplex(x,z)
Sum=Sum/numsample
FunVal=(math.factorial(dim))*Sum;
if FunVal<0.00001:
return 0.0
else:
return -math.log(FunVal)
#This is for the density X-Y
def DensityEvalDiff(z,UniformCube):
dim=len(z)
Sum=0
for gen in UniformCube:
Exponential=[-math.log(i) for i in gen]
x=[i/sum(Exponential) for i in Exponential[0:dim]]
Sum+=InreqDiffSimplex(x,z)
Sum=Sum/numsample
FunVal=(math.factorial(dim))*Sum;
if FunVal<0.00001:
return 0.0
else:
return -math.log(FunVal)
def EntropyRatio(dim):
UniformCube1=np.random.random((numsample,dim+1));
UniformCube2=np.random.random((numsample,dim+1))
IntegralSum=0; IntegralDiff=0
for gen1,gen2 in zip(UniformCube1,UniformCube2):
Expo1=[-math.log(i) for i in gen1]; Expo2=[-math.log(i) for i in gen2]
Sumz=[ (i/sum(Expo1)) + j/sum(Expo2) for i,j in zip(Expo1[0:dim],Expo2[0:dim])] #Sumz is now disbtributed as X+Y
Diffz=[ (i/sum(Expo1)) - j/sum(Expo2) for i,j in zip(Expo1[0:dim],Expo2[0:dim])] #Diffz is now distributed as X-Y
UniformCube=np.random.random((numsample,dim+1))
IntegralSum+=DensityEvalSum(Sumz,UniformCube) ; IntegralDiff+=DensityEvalDiff(Diffz,UniformCube)
IntegralSum= IntegralSum/numsample; IntegralDiff=IntegralDiff/numsample
return ((IntegralDiff +math.log(math.factorial(dim)))/ ((IntegralSum +math.log(math.factorial(dim)))))
Maxdim=11
dimlist=range(2,Maxdim)
Ratio=len(dimlist)*[0]
numsample=10000
for i in range(len(dimlist)):
Ratio[i]=EntropyRatio(dimlist[i])
Czy możesz pokazać aktualny kod? – MaxNoe
Jaki rodzaj wartości "n" jesteś zainteresowany? –
@MarkDickinson: Właściwie interesują mnie wyższe wartości n, takie jak upto 100,200 itd. Ale muszę wykreślić wszystkie wartości zaczynające się od n = 2 do 200. Dlatego chcę sprawić, żeby było wydajne. – pikachuchameleon