# Implementemos las reglas de cuadratura


```python
def cuad_pmedio(a, b, f):
    return (b-a)*f((a+b)/2)
```


```python

```


```python

```


```python

```


```python
def cuad_pmedio(a, b, f):
    """Implementación de la regla del punto medio
    
    Parameters
    ----------
    f: La función a integrar
    a: Límite inferior del intervalo
    b: Límite superior del intervalo
    
    Returns
    -------
    aprox: Aproximación de la integral por la regla del punto medio
    
    Notes
    -----
    Este código es parte del curso "Computación", Famaf
    """
    if a > b:
        raise ValueError("Oops!  Debe ser a<b")
        
    try:
        x0 = (a+b)/2
        h = f(x0)
        aprox = h*(b-a)
    except:
        print('Error: no fue posible calcular la función')
    return aprox
```


```python
def f(x):
    return x**2
```


```python
f = 9
```


```python

```


```python
cuad_pmedio(0, 1, f)
```


```python

```


```python
def cuad_trapecio(a, b, f):
    """Implementación de la regla del trapecio
    
    Parameters
    ----------
    f: La función a integrar
    a: Límite inferior del intervalo
    b: Límite superior del intervalo
    
    Returns
    -------
    aprox: Aproximación de la integral por la regla del trapecio
    
    Notes
    -----
    Este código es parte del curso "Computación", Famaf
    """
    if a > b:
        raise ValueError("Oops!  Debe ser a<b")
        return None
    try:
        h = f(a) + f(b)
        aprox = (b-a)/2*h
    except:
        print('Error: no fue posible calcular la función')
    return aprox
```


```python
def cuad_simpson(a, b, f):
    """Implementación de la regla de Simpson
    
    Parameters
    ----------
    f: La función a integrar
    a: Límite inferior del intervalo
    b: Límite superior del intervalo
    
    Returns
    -------
    aprox: Aproximación de la integral por la regla de Simpson
    
    Notes
    -----
    Este código es parte del curso "Computación", Famaf
    """
    if a > b:
        raise ValueError("Oops!  Debe ser a<b")
        return None
    try:
        x0 = (a+b)/2
        h = f(a) + f(b) + 4*f(x0)
        aprox = (b-a)/6*h
    except:
        print('Error: no fue posible calcular la función')
    return aprox
```

_____
TESTING


```python
def f(x):
    return x**2

I = cuad_pmedio(1, 2, f)
print(f'La regla del punto medio da como resultado: {I}')

I = cuad_trapecio(1, 2, f)
print(f'La regla del trapecio da como resultado: {I}')

I = cuad_simpson(1, 2, f)
print(f'La regla de simpson da como resultado: {I}')
```

    La regla del punto medio da como resultado: 2.25
    La regla del trapecio da como resultado: 2.5
    La regla de simpson da como resultado: 2.333333333333333



```python
7/3
```




    2.3333333333333335



Ahora vamos a preparar las funciones para que acepten la función o los valores


```python
def cuad_pmedio(a, b, y0):
    """Implementación de la regla del punto medio
    
    Parameters
    ----------
    y0: f evaluada en x0=(a+b)/2
    a: Límite inferior del intervalo
    b: Límite superior del intervalo
    
    Returns
    -------
    aprox: Aproximación de la integral por la regla del punto medio
    
    Notes
    -----
    Este código es parte del curso "Computación", Famaf
    """
    try:
        x0 = (a+b)/2
        aprox = x0*y0
    except:
        print('Error: no fue posible calcular la función')
    return aprox
```


```python
cuad_pmedio(0, 1, 0.5)
```




    0.25




```python
x = None
```


```python
x is not None
```




    False



¿Qué pasa si tenemos la posibilidad de tener la función o los datos?


```python
def cuad_pmedio(a, b, G=None, y0=None):
    """Implementación de la regla del punto medio
    
    Parameters
    ----------
    a: float
       Límite inferior del intervalo
    b: float
       Límite superior del intervalo
    G: function (1 parameter)
       La función a integrar
    y0: float
       El valor de y en el punto medio.
    
    Returns
    -------
    aprox: Aproximación de la integral por la regla del punto medio
    
    Notes
    -----
    Este código es parte del curso "Computación", Famaf
    """
    if a > b:
        raise ValueError("Oops!  Debe ser a<b")

    x0 = (a+b)/2
    if (G is None) and (y0 is not None):
            aprox = x0*y0
    elif (G is not None) and (y0 is None):            
        try:
            h = G(x0)
        except:
            print(('Error: no fue posible calcular la función'
                   ' Si desea ingresar un dato use y0='))
        aprox = h*(b-a)

    else:
        raise ValueError("Debe ingresar la función o los datos!")            
            
    return aprox
```


```python
cuad_pmedio(0, 1, y0=0.5)
```




    0.25




```python
cuad_pmedio(0, 1, G=f)
```




    0.25




```python

```


```python
def cuad_trapecio(x0, x1, f=None, y0=None, y1=None):
    """Implementación de la regla del trapecio
    
    Parameters
    ----------
    x0: float
       Límite inferior del intervalo
    x1: float
       Límite superior del intervalo
    f: function (1 parameter)
       La función a integrar
    y0: float
       El valor de y en el punto medio.
    y1: float
       El valor de y en el punto medio.

    
    Returns
    -------
    aprox: Aproximación de la integral por la regla del punto medio
    
    Notes
    -----
    Este código es parte del curso "Computación", Famaf
    Uso:  
        cuad_trapecio(x0, x1, f=f)
        cuad_trapecio(x0, x1, y0=f(x0), y1=f(x1))
    """
    if x0 > x1:
        raise ValueError("Oops!  Debe ser a<b")

    if (f is None) and (y0 is not None) and (y1 is not None):
            aprox = (x1-x0)*(y0+y1)/2
    elif (f is not None) and (y0 is None):            
        try:
            y0 = f(x0)
            y1 = f(x1)
        except:
            print(('Error: no fue posible calcular la función'
                   ' Si desea ingresar un dato use y0='))
        aprox = (x1-x0)*(y0+y1)/2

    else:
        raise ValueError("Debe ingresar la función o los datos!")            
            
    return aprox
```


```python
cuad_trapecio(0, 1, f)
```




    0.5




```python
cuad_trapecio(0, 1, f=f, y0=f(0), y1=f(1))
```

#### Ahora veamos si podemos hacer que la funcion "se de cuenta" de si le pasamos la funcion o los datos


```python
def contar_argumentos(func):
    def inner(*args, **kwargs):
        nargs_in = len(args) + len(kwargs)
        return func(*args, **kwargs, nargs_in=nargs_in)
    return inner
```


```python

```


```python
@contar_argumentos
def cuad_trapecio(x0, x1, f=None, y0=None, y1=None, nargs_in=None):
    """Implementación de la regla del trapecio
    
    Parameters
    ----------
    x0: float
       Límite inferior del intervalo
    x1: float
       Límite superior del intervalo
    f: function (1 parameter)
       La función a integrar
    y0: float
       El valor de y en el punto medio.
    y1: float
       El valor de y en el punto medio.

    
    Returns
    -------
    aprox: Aproximación de la integral por la regla del punto medio
    
    Notes
    -----
    Este código es parte del curso "Computación", Famaf
    Uso:  
        cuad_trapecio(x0, x1, f=f)
        cuad_trapecio(x0, x1, y0=f(x0), y1=f(x1))
    """
    if nargs_in==4:
        y1=y0        
        y0=f
        f = None
    elif nargs_in==3:
        if type(f) is float:        
            raise ValueError("Verificar los argumentos")
    else:
        raise ValueError("Verificar el número de argumentos")
            
    if x0 > x1:
        raise ValueError("Oops!  Debe ser a<b")

    if (f is None) and (y0 is not None) and (y1 is not None):
            aprox = (x1-x0)*(y0+y1)/2
    elif (f is not None) and (y0 is None):            
        try:
            y0 = f(x0)
            y1 = f(x1)
        except:
            print(('Error: no fue posible calcular la función'
                   ' Si desea ingresar un dato use y0='))
        aprox = (x1-x0)*(y0+y1)/2

    else:
        raise ValueError("Debe ingresar la función o los datos!")            
            
    return aprox
```


```python
cuad_trapecio(0, 1, f)
```




    0.5




```python
cuad_trapecio(0, 1, f(0), f(1))
```




    0.5




```python
@contar_argumentos
def cuad_simpson(x0, x2, f=None, y0=None, y1=None, y2=None, nargs_in=None):
    """Implementación de la regla de simpson
    
    Parameters
    ----------
    x0: float
       Límite inferior del intervalo
    x2: float
       Límite superior del intervalo
    f: function (1 parameter)
       La función a integrar
    y0: float
       El valor de y en el punto medio.
    y2: float
       El valor de y en el punto medio.
    
    Returns
    -------
    aprox: Aproximación de la integral por la regla de Simpson
    
    Notes
    -----
    Este código es parte del curso "Computación", Famaf
    Uso:  
        cuad_simpson(x0, x2, f=f)
        cuad_simpson(x0, x2, y0=f(x0), y2=f(x2))
        cuad_simpson(x0, x2, f)
        cuad_simpson(x0, x2, y0, y2)
    """
    
    if nargs_in==5:
        y2=y1
        y1=y0
        y0=f
        f = None
    elif nargs_in==3:
        if type(f) is float:        
            raise ValueError("Verificar los argumentos")
    else:
        raise ValueError("Verificar el número de argumentos")
            
    if x0 > x2:
        raise ValueError("Oops!  Debe ser a<b")
        
    x1 = (x0+x2)/2

    if (f is None) and (y0 is not None) and (y1 is not None):
            aprox = (x2-x0)/6 * (y0 + 4*y1 + y2)
    elif (f is not None) and (y0 is None):            
        try:
            y0 = f(x0)
            y1 = f(x1)
            y2 = f(x2)
        except:
            print(('Error: no fue posible calcular la función'
                   ' Si desea ingresar un dato use y0='))
        aprox = (x2-x0)/6 * (y0 + 4*y1 + y2)

    else:
        raise ValueError("Debe ingresar la función o los datos!")            
            
    return aprox
```


```python
cuad_simpson(0, 1, f)
```




    0.3333333333333333




```python
cuad_simpson(0, 1, f(0), f(0.5), f(1))
```




    0.3333333333333333




```python

```

______
# Reglas compuestas


```python
import numpy as np
x = np.linspace(0, 10, 11)
```


```python
x
```




    array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10.])




```python
np.diff(x)
```




    array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])




```python
def cuad_simpson_compuesta(x, f=None, y=None):
    """Implementación de la regla de simpson
    
    Parameters
    ----------
    x: list or array
       Lista de valores de x
    f: function (1 parameter)
       La función a integrar
    y: list or array
       La lista de valores de y
    
    Returns
    -------
    aprox: Aproximación de la integral por la regla de Simpson
    
    Notes
    -----
    Este código es parte del curso "Computación", Famaf
    Uso:  
        cuad_simpson(x, y=y)
        cuad_simpson(x, f=f)
    """
    import numpy as np

    # Primero verificar si la particion es regular    
    x = np.array(x)
    x.sort()    
    H = (max(x) - min(x))/(len(x)-1)
    equiesp = np.std(np.diff(x)) < H*1.e-6
    
    # Calcular los valores de y (si se pasó una función)
    if (y is None) and (f is not None):
        y = f(x)
        
    n = len(x)
    
    if equiesp:        
        impares = y[1:-1:2].sum()
        pares = y[2:-1:2].sum()        
        H = y[0] + 2*pares + 4*impares + y[-1] 
        H = H / (3*n)
        aprox = (x[-1]-x[0])*H
    else:
        aprox = 0
        for i in range(0, len(x)-2, 2):
            aprox += cuad_simpson(x[i], x[i+2], y[i], y[i+1], y[i+2])
            
    return aprox
```


```python
def f(x):
    return x**2
```


```python
x = np.linspace(0, 1, 999)
xr = np.random.uniform(0, 1, 1000)
y = f(x)
yr = f(xr)
```


```python
cuad_simpson_compuesta(x, y=y)
```




    0.3329996663329996




```python
cuad_simpson_compuesta(xr, y=yr)
```




    0.34178714534148646




```python
cuad_simpson_compuesta(x, f=f)
```




    0.3329996663329996




```python
from scipy import integrate
```


```python
integrate.quad(f, 0, 1)
```




    (0.33333333333333337, 3.700743415417189e-15)



##### Otra opción sería dar el intervalo y la función, e ir achicando la norma de la partición hasta que el error sea menor que algún valor dado.


```python
def cuad_simpson_compuesta_II(f, I, eps):
    """Implementación de la regla de Simpson
    
    Parameters
    ----------
    I: list
       Intervalo de integración, ingresado como lista de dos elementos
    f: function (1 parameter)
       La función a integrar
    
    Returns
    -------
    aprox: Aproximación de la integral por la regla de Simpson
    
    Notes
    -----
    Este código es parte del curso "Computación", Famaf
    Uso:  
        cuad_simpson_compuesta_II(f, I)
        cuad_simpson_compuesta_II(f, I)
    """
    import numpy as np

    delta = 2*eps
    n = 2
    aprox_old = (I[1]-I[0])*f((I[1]+I[0])/2)

    while delta > eps:
        x = np.linspace(I[0], I[1], n)
        aprox = cuad_simpson_compuesta(x, f=f)
        delta = abs(aprox - aprox_old)
        aprox_old = aprox
        n += 10
        if n>5000:
            break

    return aprox
```


```python
I = cuad_simpson_compuesta_II(f, [0, 1], 1.e-6)
```


```python
I
```




    0.33307618132090666




```python

```


```python

```


```python

```


```python

```

_______
# Programación simbólica


```python
import sympy
```


```python
x,y = sympy.symbols('x y')
```


```python
f = sympy.sin(x)*sympy.exp(x)
```


```python
sympy.diff(f, x)
```




$\displaystyle e^{x} \sin{\left(x \right)} + e^{x} \cos{\left(x \right)}$




```python
sympy.integrate(f)
```




$\displaystyle \frac{e^{x} \sin{\left(x \right)}}{2} - \frac{e^{x} \cos{\left(x \right)}}{2}$




```python
sympy.limit(sympy.sin(x)/x, x, 0)
```




$\displaystyle 1$




```python
sympy.limit(sympy.atan(x)/(1+x**2), x, sympy.oo)
```




$\displaystyle 0$




```python
sympy.integrate(sympy.sin(x**2), (x, -sympy.oo, sympy.oo))
```




$\displaystyle \frac{\sqrt{2} \sqrt{\pi}}{2}$




```python

```

ef2616b45b9736a6891d81de0120e33da6a07108
ipynb
Jupyter Notebook
codes/clase_16/reglas.ipynb
mlares/computacion2020
185bfded8ef1670e80b1c2cdc1fceb365d962b0e
MIT
codes/clase_16/reglas.ipynb
mlares/computacion2020
185bfded8ef1670e80b1c2cdc1fceb365d962b0e
MIT
codes/clase_16/reglas.ipynb
mlares/computacion2020
185bfded8ef1670e80b1c2cdc1fceb365d962b0e
MIT
Qwen/Qwen-72B
1. YES
2. YES