# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # Tarea 
#
# Aproxime el valor de la siguiente integral usando el método monte carlo crudo y método de reducción de varianza de muestreo estratíficado
#
# $$I=\int_{0}^{1}x^2\text{d}x=\left.\frac{x^3}{3}\right|_{x=0}^{x=1}=\frac{1}{3}\approx 0.33333$$
#
# Pasos
# 1. Cree una función que realice el método de muestreo estratíficado, recibiendo como único parámetro de entrada la cantidad de estratos y retornando las variables estratíficadas correspondientes.
#

import numpy as np
import numpy.random as r
from functools import reduce
from time import time


# Versión eficiente precargando arreglos y contenedores.
# >Se crea un contenedor para la estimación de la integral.
# >Se crea un contenedor para guardar las diferentes estimaciones.
# >Se generan aleatorios, se evalúan para cada estrato y se ponderan.
# >Se suman los estratos ponderados y se guarda el resultado.

def x2(m):
    container = np.zeros(m)
    ex = 7
    final = np.zeros(ex)
    Ns = 10**np.arange(1,ex+1)/m
    f = lambda x:x**2        
    for i,n in enumerate(Ns): 
        for j in range(m):
            container[j]=sum(f((r.rand(int(n))+j)/m))/m/n
        final[i]=sum(container)
    return final


# Ejemplo de funcionalidad:

t1=time()
print(x2(5))
print(time()-t1)

# 2. Reporte los resultados de la aproximación de la integral usando montecarlo crudo y muestreo estratíficado, en un Dataframe con la información mostrada en la siguiente imagen:
# ![image.png](attachment:image.png)

import pandas as pd
ix = 10**np.arange(1,7+1)
frame = pd.DataFrame(index=ix)
frame.index.name='términos'
simple = x2(1)
estrat = x2(5)
frame.loc[ix,'Montecarlo simple'] = simple
frame.loc[ix,'Error S'] = np.abs((1/3-np.array(simple))*100)
frame.loc[ix,'Montecarlo estratificado'] = x2(1)
frame.loc[ix,'Error E'] = np.abs((1/3-np.array(estrat))*100)
frame

# Creo que asignar pesos iguales para cada estrato no es tan efectivo como si arbitrariamente se escogieran pesos distintos para cada estrato. La forma en que asignan los pesos puede cambiar la velocidad de convergencia.

StarcoderdataJupyterScriptsDedupFiltered