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.
| f | Correlación | Ahorro |
|---|---|---|
| e^x, x² (monótona) | Negativa fuerte | 2–5× |
| sin en [0,π] (sube y baja) | Casi 0 | ~1×: no usar |
| U distintos (mal pareo) | 0 | 1×: es crudo disfrazado |
03 · Algoritmo
- 1Sortear U.
Uno solo por par:
u = random(). - 2Evaluar el par.
(f(u) + f(1-u)) / 2. Una réplica antitética. - 3Promediar 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
- 1e^x.
Factor ~3: el clásico de manual.
- 2Utilidad lineal.
150 − costo con costo uniforme: compensación perfecta parcial.
- 3Normal 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.
Compensación visible
par = (e^U + e^(1−U)) / 2
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
- ¿La correlación ronda −0,9? ¿El factor ~3?
- ¿Qué pasaría con f = sin en [0,π]?
- ¿Por qué graficar el par diagnostica antes de integrar?
Ver respuestas sugeridas
- Sí para e^x: Cov muy negativa, factor 2,5–3,5 estable.
- Correlación ~0: sin ahorro. La forma manda.
- 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.