Générer des nombres aléatoires à partir de la «distribution uniforme inclinée» de la théorie mathématique

9

Dans un certain but, j'ai besoin de générer des nombres aléatoires (données) à partir de la distribution "uniforme en pente". La "pente" de cette distribution peut varier dans un intervalle raisonnable, et alors ma distribution devrait changer d'uniforme à triangulaire en fonction de la pente. Voici ma dérivation:

entrez la description de l'image ici

Rendons les choses simples et générons des données de à (le bleu, le rouge est la distribution uniforme). Pour obtenir la fonction de densité de probabilité de la ligne bleue, j'ai juste besoin de l'équation de cette ligne. Donc:B0B

f(x)=tg(φ)x+Y(0)

et depuis (photo):

tg(φ)=1/BY(0)B/2Y(0)=1Btg(φ)B2

Nous avons cela:

F(X)=tg(φ)X+(1B-tg(φ)B2)

Puisque est PDF, CDF est égal à:F(X)

F(X)=tg(φ)X22+X(1B-tg(φ)B2)

Faisons maintenant un générateur de données. L'idée est que si je fixe , des nombres aléatoires peuvent être calculés si j'obtiens des nombres de partir d'une distribution uniforme comme décrit ici . Ainsi, si j'ai besoin de 100 nombres aléatoires de ma distribution avec fixe , alors pour tout de distribution uniforme il y a de "distribution inclinée", et peut être calculé comme:x ( 0 , 1 ) φ , B t i ( 0 , 1 ) x i xφ,BX(0,1)φ,Btje(0,1)XjeX

tg(φ)Xje22+Xje(1B-tg(φ)B2)-tje=0

A partir de cette théorie, j'ai fait du code en Python qui ressemble à:

import numpy as np
import math
import random
def tan_choice():
    x = random.uniform(-math.pi/3, math.pi/3)
    tan = math.tan(x)
    return tan

def rand_shape_unif(N, B, tg_fi):
    res = []
    n = 0
    while N > n:
        c = random.uniform(0,1)
        a = tg_fi/2
        b = 1/B - (tg_fi*B)/2
        quadratic = np.poly1d([a,b,-c])
        rots = quadratic.roots
        rot = rots[(rots.imag == 0) & (rots.real >= 0) & (rots.real <= B)].real
        rot = float(rot)
        res.append(rot)
        n += 1
    return res

def rand_numb(N_, B_):
    tan_ = tan_choice()
    res = rand_shape_unif(N_, B_, tan_)
    return res

Mais les nombres générés à partir de rand_numbsont très proches de zéro ou de B (que j'ai défini comme 25). Il n'y a aucun écart, lorsque je génère 100 nombres, ils sont tous proches de 25 ou tous proches de zéro. En un seul passage:

num = rand_numb(100, 25)
numb
Out[140]: 
[0.1063241766836174,
 0.011086243095907753,
 0.05690217839063588,
 0.08551031241199764,
 0.03411227661295121,
 0.10927087752739746,
 0.1173334720516189,
 0.14160616846114774,
 0.020124543145515768,
 0.10794924067959207]

Il doit donc y avoir quelque chose de très mal dans mon code. Quelqu'un peut-il m'aider avec ma dérivation ou mon code? Je suis fou de ça maintenant, je ne vois aucune erreur. Je suppose que le code R me donnera des résultats similaires.

Robert
la source
2
ϕXB-XBtheta-11nRx<-runif(n,-1,1);x<-(ifelse(runif(n,-1,1)>theta*x,-x,x)+1)*(B/2)

Réponses:

9

(0,B)

B2bronzerϕ<2.
B=25ϕ±bronzer-12625

BX

F(X)=t
F(X)=12bronzerϕX2+(1B-B2bronzerϕ)X.
F(0)=0F(B)=1F(0,B)

bronzerϕ>0

X=1bronzerϕ(B2bronzerϕ-1B+(B2bronzerϕ-1B)2+2bronzerϕt.)
bronzerϕ<0bronzerϕ+Δ

Voici du code R.

phi <- pi/8; B <- 2
f <- function(t) (-(1/B - 0.5*B*tan(phi)) + 
       sqrt( (1/B - 0.5*B*tan(phi))**2 + 2 * tan(phi) * t))/tan(phi)
hist(f(runif(1e6)))

histogramme 1

ϕ<0

phi <- -pi/8
hist(f(runif(1e6)))

entrez la description de l'image ici

Elvis
la source
1
F(X)
ϕB