Está en la página 1de 12

Simulación Monte Carlo

Algoritmos Page 1
Algoritmos Page 2
Al ejecutar este script para n=10^4, y luego n=10^6, vemos que la probabilidad obtenida
concuerda muy bien con la longitud del intervalo [L,R]. Para n=100, no se puede apreciar
que la distribución de número en [L,R] es uniforme.

Una consecuencia de la distribución uniforme, es que para n grande el comando rand elige
cualquier número entre 0 y 1 con igual probabilidad (la elección es insesgada).

Para una mejor visualización construiremos un vector aleatorio de números enteros que

Algoritmos Page 3
Para una mejor visualización construiremos un vector aleatorio de números enteros que
varíen del 1 al 10. Aquí cada decil formaría los intervalos [0,1], [1,2], …,[9,10].

Para el caso n=1e4, obtenemos

Si aumentamos a n=1e6 (un millón de repeticiones) obtenemos

Algoritmos Page 4
rand(1)
randn(1)

Esto nos dice que a mayor número de repeticiones podremos apreciar que el comando
rand nos da una distribución uniforme al elegir números entre 1 y 10. En otras palabras,
cualquier entero entre 1 y 10 tiene igual probabilidad de ser elegido por el comando rand
(luego de haberlo reescalado, trasladado y aplicado el comando ceil).

Podemos concluir que una simulación aleatoria debe realizarse un gran número de veces,
caso contrario se corre el peligro que no se cumpla una elección al azar con el tipo de
distribución elegida. En nuestro caso, al usar rand estamos pidiendo una distribución
uniforme.

Examine qué ocurre si elige 20 o 100 repeticiones.

Algoritmos Page 5
El siguiente script resuelve parcialmente el problema de tirar un dardo n veces sobre el
cuadrado [-1,1]x[-1,1] (sin sesgamiento, esto es, con distribución uniforme) para estimar
el valor de pi.

Compilamos:
(no poner 1e9 porque Matlab no
soporta un vector tan grande para
rand).

Ahora apreciemos como está distribuida la data para n = 1e4,


aumentando simplemente algunas líneas de código después de
la línea 7:

y conseguimos la siguiente figura (para n = 1e4):

Algoritmos Page 6
Ahora vamos a predisponer los dardos que caigan cerca al origen. Para ello,
usaremos una distribución normal: randn

La asignación r = randn(n,1),
produce un vector columna nx1 cuyas entradas siguen una distribución normal
con media cero y desviación estándar uno.

Al compilar, obtenemos:

Algoritmos Page 7
La distribución normal en principio nos puede dar cualquier número real, pero con
mayor probabilidad de que aparezca alrededor de la media, que lejos de ella.

El siguiente script implementa lanzamientos sesgados (con predilección a que los


dardos caigan cercanos al origen):

Algoritmos Page 8
Observar el porqué se tuvo que también contar el número de dardos que se
encuentran dentro del cuadrado, para que la fórmula para piEst sea al menos
más coherente al calcularla.
Se aprecia que al realizar este experimento (sesgado, al tener preferencia de que
los dardos caigan cerca al origen), el valor estimado de pi llega a ser incorrecto.

Introducimos ahora técnicas para simplifcar y vectorizar una sucesión estructurada


de operaciones lógicas (para eliminar bucles for cuando se pueda). Considere el
siguiente script:

Algoritmos Page 9
cuya compilación nos da:

Vemos que B es un vector lógico de 0's y 1's. Podemos contar el número de


veces que las entradas de x son menores que y, simplemente usando el
comando sum(B), que nos da la suma de las entradas de B.
En caso que ahora consideremos que los arreglos x y y, forman 5 puntos, y
deseamos saber si estos puntos se encuentran dentro o sobre el círculo
unitario, podemos evitar el uso de un bucle for con el siguiente código:

lo cual nos da:


ans = 2
El hecho de prescindir del uso de un bucle for y usar una estructura lógica
para ello se llama vectorización.

Así, podemos vectorizar el script que estima el número pi usando una distribución
uniforme (el script que usa el comando rand):

Algoritmos Page 10
La conveniencia en vectorizar una parte del código es que Matlab opera de manera
más eficiente y rápida bloques de códigos que estén vectorizados.

Los comandos rand y randn son llamados generadores de números seudo-aleatorios.


Esto se debe a que realmente hay una fórmula para obtener sus valores. Por ejemplo,
si hacemos que la semilla (seed, en inglés) sea cero, siempre obtendremos el mismo
valor cuando compilemos un script que contenga estos generadores. Por ejemplo,
compile dos o tres veces el siguiente script:

obtenemos:

Posiblemente Ud. obtenga valores diferentes. Ahora compile el siguiente script dos o
tres veces:

obtenemos siempre

Algoritmos Page 11
Esto nos hace sospechar que hay una fórmula generadora detrás del uso del comando
rand. Esto en verdad es así. Lo que sucede es que si borramos la línea 1, dejamos a
Matlab que escoja la semilla (seed). Por ejemplo, esta semilla podría ser el contador
de la hora de la computadora, el cual siempre para cambiando.

En conclusión, podemos confiar en el uso de los comando rand y randn cuando


repetimos un experimento varias veces. Estas funciones han sido puestas a prueba
por muchos ingenieros y estadísticos, y nosotros también vamos a confiar en el uso
de estas funciones y las consideraremos como realmente aleatorias (para un número
grande de repeticiones).

Algoritmos Page 12

También podría gustarte