Método de Monte Carlo · Tema 26

Variables antitéticas

Parear U con 1−U: lo alto compensa lo bajo y el promedio se calma.

01 · Punto de partida

Compensar en vez de acumular ruido

Si U = 0,9 da f alta, 1−U = 0,1 da f baja: el par promedia al centro. Con f monótona, los pares están negativamente correlacionados y su promedio varía menos que dos muestras independientes.

Cuesta lo mismo (2 evaluaciones) y el ± se achica gratis.

  • ¿Mi f es monótona en el intervalo?
  • ¿Pareo con el mismo U?
  • ¿La correlación es negativa?
  • ¿Cuánto cae s?

02 · Definición

El par que se compensa

👯

Par

Dos evaluaciones atadas: f(U) y f(1−U). Una réplica = el promedio del par.

📉

Cov < 0

Si f sube, una sube y la otra baja: se cancelan. Ahí está el ahorro.

📏

Monótona

Condición típica: f creciente o decreciente. e^x, x² en [0,1], lineales.

Cuándo compensan y cuándo no.
fCorrelaciónAhorro
e^x, x² (monótona)Negativa fuerte2–5×
sin en [0,π] (sube y baja)Casi 0~1×: no usar
U distintos (mal pareo)01×: es crudo disfrazado

03 · Algoritmo

U→Par→Promedio
  1. 1
    Sortear U.

    Uno solo por par: u = random().

  2. 2
    Evaluar el par.

    (f(u) + f(1-u)) / 2. Una réplica antitética.

  3. 3
    Promediar pares.

    Media y s sobre pares, no sobre 2N sueltos.

Mismo U
Obligatorio: con U distintos no hay correlación y no hay ahorro.
s sobre pares
La varianza que importa es la de los pares, no la de f suelta.
Generalización
En normal: Z y −Z. En cualquier simétrica: x y su espejo.

04 · Ejemplos

  1. 1
    e^x.

    Factor ~3: el clásico de manual.

  2. 2
    Utilidad lineal.

    150 − costo con costo uniforme: compensación perfecta parcial.

  3. 3
    Normal con Z/−Z.

    Par (g(Z), g(−Z)) para payoff simétricos.

05 · Representación en Python

El par bien hecho en 5 líneas

Python en tu navegador. Compará correlación y s.

import random
import math
import statistics

def f(x):
    return math.exp(x)

N = 5000
pares = []
ys1, ys2 = [], []
for _ in range(N):
    u = random.random()
    a, b = f(u), f(1-u)
    pares.append((a+b)/2)
    ys1.append(a); ys2.append(b)

print("media:", round(sum(pares)/N, 4))
print("s pares:", round(statistics.pstdev(pares), 4))
print("s crudo:", round(statistics.pstdev(ys1), 4))

06 · Exploración

Laboratorio: pares que se abrazan en diagonal

Cada punto es un par (f(U), f(1−U)) para e^x. La nube baja de izquierda a derecha: correlación negativa. A la derecha, el factor de ahorro.

EXPERIMENTO 26

Compensación visible

par = (e^U + e^(1−U)) / 2

Los resultados numéricos aparecen debajo.
Correlación—
Factor ahorro—
Media pares—
Lectura—

Tocá «Parear» para generar N pares.

Si la nube subiera (correlación positiva), el par amplificaría el ruido. Aquí baja: ahorra.

Preguntas para explorar

  1. ¿La correlación ronda −0,9? ¿El factor ~3?
  2. ¿Qué pasaría con f = sin en [0,π]?
  3. ¿Por qué graficar el par diagnostica antes de integrar?
Ver respuestas sugeridas
  1. Sí para e^x: Cov muy negativa, factor 2,5–3,5 estable.
  2. Correlación ~0: sin ahorro. La forma manda.
  3. La pendiente de la nube anticipa el ahorro sin calcular integrales.

07 · Comprensión

Confusiones frecuentes

«Dos U independientes son antitéticas»

No: antitético es (U, 1−U) con el mismo U. Independientes = crudo.

«Vale para cualquier f»

Solo monótonas suaves. Probar con tu f y medir.

«El error se calcula sobre 2N»

Sobre N pares: la unidad es el par, no la evaluación suelta.

«Más pares siempre mejor que crudo»

Solo si Cov < 0. Si Cov ≥ 0, el par no ahorra o empeora.

08 · Práctica guiada

Ejercicios con Python

Ejercicio 1: correlación del par

Calculá la correlación entre f(U) y f(1−U) para e^x.

import random
import math
import statistics

N = 5000
a = []
b = []
for _ in range(N):
    u = random.random()
    a.append(math.exp(u)); b.append(math.exp(1-u))
ma, mb = sum(a)/N, sum(b)/N
cov = sum((x-ma)*(y-mb) for x, y in zip(a, b)) / N
print(round(cov / (statistics.pstdev(a)*statistics.pstdev(b)), 3))
Ver solución razonada

≈ −0,95: casi perfectamente opuestas. Por eso el factor ~3.

Ejercicio 2: factor para x²

Medí el factor para x² en [0,1].

import random
import statistics

N = 5000
crudo = [random.random()**2 for _ in range(2*N)]
pares = []
for _ in range(N):
    u = random.random()
    pares.append((u**2 + (1-u)**2)/2)
print(round((statistics.pstdev(crudo)/statistics.pstdev(pares))**2, 2))
Ver solución

~2,5. Monótona en [0,1] (creciente): compensa bien.

Ejercicio 3: dónde no usar

Probá con sin en [0,π] y mostrá que no ahorra.

Ver una posible respuesta
import random
import math
import statistics

N = 5000
crudo = [math.sin(random.uniform(0, math.pi)) for _ in range(2*N)]
pares = []
for _ in range(N):
    u = random.uniform(0, math.pi)
    v = math.pi - u  # espejo
    pares.append((math.sin(u) + math.sin(v)) / 2)
print(round((statistics.pstdev(crudo)/statistics.pstdev(pares))**2, 2))

~1,0: simétrica, no monótona. El par no compensa: elegir otra técnica.

09 · Síntesis

Ideas para recordar

  • Par = (f(U)+f(1−U))/2 con el mismo U.
  • Ahorra si Cov < 0, típico en monótonas suaves.
  • Error sobre pares, no sobre 2N sueltos.
  • Factor 2–5× cuando aplica; ~1× cuando no.
  • Diagnosticar con la nube del par antes de usar.

En el próximo tema corregiremos con lo conocido: las variables de control.