Sunteți pe pagina 1din 10

Simulare

April 21, 2023

1 Simularea unui vector aleator continuu uniform distribuit pe un


domeniu dreptunghiular
Ce inseamna a simula vectorul (𝑋, 𝑌 )? Vectorul (𝑋, 𝑌 ) este distribuit aleator, adica nu are o
valoare fixa. Cunoastem doar probabilitatea ca acesta sa ia o valoare intr-un anumit domeniu. A
simula acest vector inseamna a alege o valoare pe care acesta o poate lua, tinand cont de distributia
sa.
Dorim sa simulam un vector (𝑋, 𝑌 ) distribuit uniform pe un dreptunghi, deci avem 2 cerinte: -
valorile luate de vector sa se afle doar in dreptunghi - fiecare valoare posibila “sa aiba aceeasi
probabilitate” de a fi aleasa
Stim ca daca vectorul (𝑋, 𝑌 ) este uniform distribuit pe dreptunghiul [𝑎, 𝑏] × [𝑐, 𝑑], atunci variabila
𝑋 este distribuita uniform pe intervalul [𝑎, 𝑏], si variabila 𝑌 este distribuita uniform pe intervalul
[𝑐, 𝑑].
De asemenea, se poate arata ca variabilele 𝑋 si 𝑌 sunt independente. Atunci, putem simula vectorul
(𝑋, 𝑌 ) simuland separat variabilele 𝑋 si 𝑌 .
Variabilele 𝑋 si 𝑌 sunt distribuite uniform pe intervalele [𝑎, 𝑏] si [𝑐, 𝑑], deci stim sa le simulam!
In general, atunci cand simulam, presupunem ca avem la dispozitie o functie care ne genereaza uni-
form numere aleatoare in intervalul [0, 1]. In pseudocod vom numi aceasta functie urand(uniform
random).
Avem la dispozitie functia urand pentru a genera uniform numere aleatoare in intervalul [0, 1].
Cum ajungem sa generam in intervalul [𝑎, 𝑏]?
Primul pas este sa inmultim rezultatul lui urand cu 𝑏 − 𝑎, obtinand un numar in intervalul [0 ⋅ (𝑏 −
𝑎), 1 ⋅ (𝑏 − 𝑎)], adica in intervalul [0, 𝑏 − 𝑎].
Tot ce mai lipseste este sa adunam 𝑎, obtinand [0 + 𝑎, 𝑏 − 𝑎 + 𝑎] = [𝑎, 𝑏].
Pseudocodul pentru a simula variabila 𝑋, uniform distribuita pe intervalul [𝑎, 𝑏] arata atunci astfel:
x = urand() * (b - a) + a;
Stiind ca a simula vectorul (𝑋, 𝑌 ) distribuit uniform pe domeniul [𝑎, 𝑏] × [𝑐, 𝑑] este echivalent cu a
simula variabila 𝑋 pe intervalul [𝑎, 𝑏] si variabila 𝑌 pe intervalul [𝑐, 𝑑], rezulta urmatorul pseudocod
pentru simularea vectorului:
x = urand() * (b - a) + a;
y = urand() * (c - d) + c;

1
Sa transformam acest pseudocod in cod Python, pe care il putem rula. Vom folosi libraria numpy
pentru a avea acces la o functie de tip urand:
[ ]: import numpy as np

Functia ce ne intereseaza este np.random.rand, care returneaza o valoare distribuita uniform din
intervalul [0, 1).
Vom defini functia sim_unif_vector(a, b, c, d), care va simula un vector distribuit uniform pe
domeniul [𝑎, 𝑏] × [𝑐, 𝑑]:

[ ]: def sim_unif_vector(a, b, c, d):


x = np.random.rand()*(b-a)+a
y = np.random.rand()*(d-c)+c
return [x, y]

Sa apelam aceasta functie, alegand domeniul [−1, 1] × [0, 2]:

[ ]: sim_unif_vector(-1, 1, 0, 2)

[ ]: [0.20292853288842783, 1.2726988992162442]

Observam ca valorile returnate par sa apartina domeniului dorit. Simulam 1000 de valori pentru a
ne convinge de acest fapt:
[ ]: samples = []
for i in range(0, 1000):
samples.append(sim_unif_vector(-1, 1, 0, 2))

Putem reprezenta aceste observatii grafic cu ajutorul librariei matplotlib:


[ ]: import matplotlib.pyplot as plot

Acum vom reprezenta grafic fiecare dintre cele 1000 de observatii:


[ ]: for i in range(0, 1000):
x = samples[i][0]
y = samples[i][1]
plot.scatter(x, y)

2
Observam ca toate punctele sunt situate in dreptunghiul [𝑎, 𝑏] × [𝑐, 𝑑], si ca nu exista zone ale
acestui dreptunghiu in care sa se afle mult mai multe puncte decat in alte zone, adica punctele sunt
distribuite uniform pe acest dreptunghi.
Observatie: Codul Python scris mai sus este ineficient, deoarece reprezentam observatie cu obser-
vatie. Puteam reprezenta toate observatiile dintr-un singur apel al functiei plot.scatter, dar am
ales codul cel mai simplu pentru a fi inteles mai usor.

2 Simularea unui vector aleator continuu uniform distribuit pe


domenii nedreptunghiulare
Vom considera drept domeniu discul unitar, adica cercul de centru (0, 1) si raza 1, si interiorul sau.

[ ]: circle = plot.Circle((0, 1), 1, clip_on = False)


fig, ax = plot.subplots()
ax.add_patch(circle)
plot.axis((-3, 3, -3, 3))
ax.set_aspect('equal', adjustable='box')
plot.show()

3
Dorim sa simulam un vector (𝑋, 𝑌 ) distribuit uniform pe acest cerc. Stim sa simulam vectori
distribuiti uniform pe dreptunghiuri.
Cautam un dreptunghi ce contine intreg cercul. Vizual, observam ca dreptunghiul [−2, 2] × [−2, 2]
contine intreg cercul.
[ ]: rectangle = plot.Rectangle((-2, -1), 4, 4, color="r", alpha=0.5)
circle = plot.Circle((0, 1), 1, clip_on = False)
fig, ax = plot.subplots()
ax.add_patch(circle)
ax.add_patch(rectangle)
plot.axis((-3, 3, -3, 3))
ax.set_aspect('equal', adjustable='box')
plot.show()

4
Pentru a simula uniform puncte din interiorul cercului, vom simula puncte din dreptunghi pana
gasim unul care se afla si in cerc.
Altfel spus, simulam un punct din dreptunghi. Daca punctul se afla si in cerc, atunci acesta este
punctul ce ne intereseaza. Altfel, simulam un alt punct, pana cand gasim unul ce se afla si in cerc.
Pseudocodul arata astfel:
do{
genereaza un punct (x, y) din dreptunghi;
} while(punctul generat nu se afla si in cerc);
Generarea punctului din dreptunghi se realizeaza ca mai sus, anume:
x = urand() * (b - a) + a;
y = urand() * (d - c) + c;
Cercul de centru (0, 1) si raza 1 are ecuatia:

(𝑥 − 0)2 + (𝑦 − 1)2 = 12

Discul corespunzator acestui cerc contine si punctele din interiorul cercului, deci are aceasta ecuatie:

(𝑥 − 0)2 + (𝑦 − 1)2 ≤ 12

5
Pentru a obtine punctele ce nu se afla in acest disc, este suficient sa negam ecuatia de mai sus, ceea
ce se poate face matematic prin inlocuirea semnului ≤ cu >:

(𝑥 − 0)2 + (𝑦 − 1)2 > 12

Deci pseudocodul arata astfel:


do{
x = urand() * (b - a) + a;
y = urand() * (d - c) + c;
} while (x^2 + (y-1)^2 > 1)
Acum vom scrie acelasi cod in limbajul Python, folosind functia sim_unif_vector de mai sus.
In acest limbaj nu exista do while, deci va trebuie sa il simulam folosind while:
[ ]: [x, y] = sim_unif_vector(-2, 2, -2, 2)
while x*x + (y - 1)*(y - 1) > 1:
[x, y] = sim_unif_vector(-2, 2, -2, 2)

Aceasta metoda de simulare a vectorilor aleatori continui este cunoscuta drept metoda respin-
gerii, deoarece generam puncte dintr-un dreptunghi si le respingem pe cele care nu se afla si in
domeniul ce ne intereseaza.
Metoda respingerii functioneaza pentru orice tip de domeniu, nu numai unul circular. Este suficient
sa gasim un dreptunghi care sa acopere intregul domeniu de interes!
Notand cu 𝐺 domeniul in care vrem sa simulam, si cu 𝐷 domeniul dreptunghiular care il include
pe 𝐺, se poate demonstra ca probabilitatea ca un punct simulat in domeniul 𝐷 sa se afle si in
domeniul 𝐺 este:
aria(𝐺)
aria(𝐷)

Putem folosi orice dreptunghi 𝐷 care include 𝐺, dar ne dorim sa alegem unul care duce la un
algoritm cat mai rapid. Algoritmul este cu atat mai rapid cu cat probabilitatea de mai sus creste.
Pentru ca probabilitatea sa creasca, trebuie ca aria(𝐷) sa scada, deci ne dorim un dreptunghi de
arie minima. Acest fapt se observa si din grafic, deoarece un dreptunghi de arie mai mica se afla
mai aproape de cerc.
Revenind la cercul de mai sus, observam ca dreptunghiul [−1, 1] × [0, 2] este dreptunghiul de arie
minima ce acopera complet cercul!
[ ]: rectangle = plot.Rectangle((-1, 0), 2, 2, color="r", alpha=0.5)
circle = plot.Circle((0, 1), 1, clip_on = False)
fig, ax = plot.subplots()
ax.add_patch(circle)
ax.add_patch(rectangle)
plot.axis((-3, 3, -3, 3))
ax.set_aspect('equal', adjustable='box')
plot.show()

6
3 Exemplu simulare vector continuu uniform distribuit pe un tri-
unghi
Dorim sa geneream uniform puncte pe domeniul dat de urmatorul sistem de inecuatii:

0 ≤ 𝑥, 𝑦 ≤ 1
{
𝑦≤𝑥

Pentru a ne convinge ca acest domeniu este intr-adevar un triunghi, il vom reprezenta grafic.
Primele 2 inegalitati ne impun limite pentru 𝑥 si 𝑦.
Vom reprezenta mai intai grafic ultima inecuatie. Primul pas este sa reprezentam linia 𝑦 = 𝑥, si
apoi sa consideram toate punctele de sub ea, datorita semnului ≤:
[ ]: import matplotlib.pyplot as plot

[ ]: x = np.linspace(0, 4, 1000)
y = x
plot.plot(x, y)
plot.fill_between(x, y, alpha = 0.5)
plot.show()

7
Adaugand si cele 2 inecuatii ce limiteaza valorile lui 𝑥 si 𝑦, vom obtine un triunghi mai mic:
[ ]: x = np.linspace(0, 4, 1000)
y = x
plot.plot(x, y)
plot.fill_between(x, y, where = (0 <= x) & (x <= 1) & (0 <= y) & (y <= 1),␣
↪alpha = 0.5)

plot.show()

8
Observam ca cel mai bun dreptunghi ce contine intreg domeniul cautat este dreptunghiul [0, 1] ×
[0, 1]. Rezulta urmatorul cod Python de simulare:

[ ]: def sim_unif_triangle():
x = np.random.rand()
y = np.random.rand()
while y > x:
x = np.random.rand()
y = np.random.rand()
return [x, y]

[ ]: sim_unif_triangle()

[ ]: [0.2884488751475007, 0.0784346645417322]

[ ]: for i in range(0, 1000):


sample = sim_unif_triangle()
sample_x = sample[0]
sample_y = sample[1]
plot.scatter(sample_x, sample_y)

9
10

S-ar putea să vă placă și