Ho due variabili aleatorie X e Y, che sono uniformemente distribuiti sul simplex: Stima della densità di probabilità della somma di variabili casuali uniformi in python
voglio valutare la densità della loro somma:
Dopo aver valutato quanto sopra integrale, il mio obiettivo finale è quello di calcolare il seguente integrale:
per calcolare ° e primo integrale, sto generando punti uniformemente distribuiti in simplex e poi controllando se appartengono alla regione desiderata nell'integrale di cui sopra e prendendo la frazione di punti per valutare la densità di cui sopra.
Una volta calcolata la densità di cui sopra, sto seguendo una procedura simile per calcolare l'integrale logaritmo di cui sopra per calcolare il suo valore. Tuttavia, questo è stato estremamente inefficiente e richiedendo molto tempo per 3-4 ore. Qualcuno mi può suggerire un modo efficace per risolvere questo in Python? Sto usando il pacchetto Numpy.
Ecco il codice
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])
Puoi mostrare il codice attuale? – MaxNoe
Che tipo di valori di 'n' sei interessato a? –
@MarkDickinson: In realtà sono interessato ai valori più alti di n, come fino a 100.200 ecc. Ma ho bisogno di rappresentare graficamente tutti i valori a partire da n = 2 fino a 200. Ecco perché voglio renderlo efficiente. – pikachuchameleon