77
Programacion con Python Release 0.4 Oscar Vargas Torres 02 de September de 2013

Anal is is Numeric o Con Python

Embed Size (px)

Citation preview

Page 1: Anal is is Numeric o Con Python

Programacion con PythonRelease 0.4

Oscar Vargas Torres

02 de September de 2013

Page 2: Anal is is Numeric o Con Python
Page 3: Anal is is Numeric o Con Python

Índice general

1 Programación básica 31.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2 Python básico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.3 Expresiones y operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.4 Procedimientos y funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101.5 Estructuras de control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2 Gráficas 232.1 Gráficas simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232.2 Gráficas de contorno . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272.3 Gráficas en 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282.4 Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292.5 Gráficas de algunos campos simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

3 Álgebra lineal 333.1 Arreglos de NumPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333.2 Álgebra Lineal básica con NumPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363.3 Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

4 Polinomios e interpolación 394.1 Introducción a la Interpolación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394.2 Interpolación segmentaria (splines) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

5 Ajuste de funciones 435.1 Regresión por mínimos cuadrados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

6 Raíces de ecuaciones no lineales 496.1 Introducción: Raíces de ecuaciones no lineales . . . . . . . . . . . . . . . . . . . . . . . . . . 496.2 Un vistazo a la librería GNU Scientific Library (GSL) . . . . . . . . . . . . . . . . . . . . . . 54

7 Diferenciación e integración numérica 597.1 Diferenciación numérica básica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 597.2 Integración numérica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

i

Page 4: Anal is is Numeric o Con Python

8 Ecuaciones Diferenciales Ordinarias 658.1 Ecuaciones Diferenciales Ordinarias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 658.2 PROYECTO FINAL: Rescatando a la tripulación del Apollo 13 . . . . . . . . . . . . . . . . 70

9 Índices y tablas 73

Índice 73

ii

Page 5: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

Contents:

Índice general 1

Page 6: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

2 Índice general

Page 7: Anal is is Numeric o Con Python

CAPÍTULO 1

Programación básica

1.1 Introducción

1.1.1 ¿Por qué aprender a programar?

• Porque es una habilidad que aumenta tus posibilidades de adquirir un mejor empleo.

• Para realizar cálculos intensos, es necesario utilizar una computadora, pues hacerlos a mano sería muytardado o imposible.

• Ejemplos de áreas en las que puedes aplicar la programación:

– Métodos numéricos: Resuelva de manera numérica (utilizando el método de Euler) el sistemamasa-resorte dado por la ecuación diferencial

mu′′ + βu′ + ku = F (t), u(0) = U0, u′(0) = 0

Sistema masa resorte que se describe mediante una ecuación diferencial

– Graficación. A continuación se muestra un histograma obtenido a partir de una distribución deprobabilidad normal.

3

Page 8: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

import matplotlib.pyplot as pltimport numpy as npx = np.random.randn(1000)plt.hist(x, 20)plt.grid()plt.show()

4 3 2 1 0 1 2 30

20

40

60

80

100

120

140

160

1.1.2 Python como primer lenguaje de programación

Se ha escogido Python como un lenguaje de programación porque combina capacidadades notables con unasintáxis limpia, simple y compacta. Enunciamos algunas características de Python:

• Python es fácil de aprender y es muy apropiado para un curso introductorio de programación.

• Es muy similar a Matlab y un buen lenguaje para hacer cómputo matemático.

• Es fácil de combinar con lenguajes compilados como Fortran, C y C++, que son lenguajes ampliamenteusados para cómputo científico.

1.1.3 Instalación de software utilizado en el curso

Se requiere:

• WinPython 3.3 → Puedes descargarlo e instalarlo de http://code.google.com/p/winpython/downloads/list

4 Capítulo 1. Programación básica

Page 9: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

1.1.4 Temario

1. Programación con software matemático.

(a) Conceptos básicos de programación (con Python 3.x). Ejemplo: funciones.

(b) Lectura y escritura de datos simple.

2. Gráficas con software matemático.

(a) Matplotlib y Numpy.

(b) Gráficas simples en 2D y en 3D.

import matplotlib.pyplot as pltimport numpy as npx = np.arange(-2, 2, 0.01)y = np.arange(-2, 2, 0.01)X, Y = np.meshgrid(x, y)ellipses = X*X/9 + Y*Y/4 - 1cs = plt.contour(ellipses)plt.clabel(cs)plt.show()

0 50 100 150 200 250 300 3500

50

100

150

200

250

300

350

-0.800

-0.600

-0.400

-0.400

-0.200

-0.200

0.0000.000

0.0000.000

0.200 0.200

0.2000.200

Gráfica de contornos.

3. Álgebra lineal.

(a) Matrices y vectores.

(b) Sistemas de ecuaciones lineales.

1.1. Introducción 5

Page 10: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

Para resolver el sistema de ecuaciones lineales Ax = b dado por A =

[3 2−1 2

]y b =

[182

]:

import numpy as npA = np.array([[3.0, 2.0], [-1.0, 2.0]])b = np.array([18.0, 2.0])from numpy.linalg import solvex = solve(A, b)print(x) # Solución: x = [4.0, 3.0]

4. Polinomios e interpolación.

import numpy as np

from scipy.interpolate import interp1dimport matplotlib.pyplot as pltx = np.linspace(0, 10, 10)y = np.cos(-x**2/8.0)f = interp1d(x, y)f2 = interp1d(x, y, kind='cubic')xnew = np.linspace(0, 10, 40)plt.plot(x, y, 'o', xnew, f(xnew), '-', xnew, f2(xnew), '--')plt.legend(['data', 'linear', 'cubic'], loc='best')plt.show()

5. Ajuste de funciones.

(a) Regresión.

(b) Interpolación.

6. Raíces de ecuaciones no lineales.

Se tratará de hallar las raíces de ecuaciones. Es decir, el problema es: resolver f(x) = 0 para x.Ejemplo: determine la raíz más grande de h(x) = 2x3 − 11.7x2 + 17.7x− 5 en forma gráfica.

import numpy as npimport matplotlib.pyplot as pltx = np.linspace(0, 4)y = 2 * x**3 - 11.7 * x**2 + 17.7 * x - 5plt.plot(x, y)plt.grid()plt.show()

6 Capítulo 1. Programación básica

Page 11: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.06

4

2

0

2

4

6

8

7. Funciones de splines e interpolación no lineal.

8. Diferenciación e integración numérica.

9. Problemas de valor inicial de ecuaciones diferenciales ordinarias.

El movimiento vertical de un peso sujeto a un resorte que obedece la Ley de Hooke, y que tiene unestímulo senoidal externo se puede modelar con la ecuación diferencial:

y + 2cy + ω20y = F0 sin(ωt) (1.1)

donde c, ω0 y ω son números reales positivos. Considéremos el caso en que c < ω0, que corresponde aun sistema sub-amortiguado. Además suponga que ω < ω0. Con estas suposiciones, la solución generalde (1.1) se puede expresar como y = yu + yd, donde

yu = C1e−ct cos

(t√

ω20 − c2

)+ C2e

−ct sin(t√ω20 − c2

)(1.2)

yd = F0M(ω) sin[ωt+ ϕ(ω)] (1.3)

C1, C2 dependen de las condiciones iniciales y

M(ω) =1√

(ω20 − ω2)2 + 4c2ω2

(1.4)

ϕ(ω) = arctan(

−2cω

ω20 − ω2

)− π < ϕ(ω) < 0 (1.5)

1.1. Introducción 7

Page 12: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

Figura 1.1: Regla trapezoidal (Integración numérica)

1.2 Python básico

Para iniciar con lo más básico, te recomiendo estudiar el Tutorial de Python (no es necesario que revises todoel tutorial, pero si es importante que empieces lo más pronto posible, y que vayas practicando cada temaque se vea en clase) en http://docs.python.org/3/tutorial/index.html (este tutorial está en inglés, pero es eltutorial adecuado para la versión de Python que estaremos usando en el curso). También puedes apoyarteen una versión del tutorial en español disponible en http://docs.python.org.ar/tutorial/3/index.html.

Especialmente importantes son las secciones 1 a 5 del tutorial. Asegúrate de estudiar al menos estas seccionesdel tutorial.

1.2.1 Práctica 1

1. Descarga WinPython de http://code.google.com/p/winpython/downloads/list y ejecuta el instala-dor (Verifica primero si tienes una computadora con un sistema operativo de 64 bits o de 32 bits ydescarga la versión más apropiada para ti. Si tienes dudas, pregunta a tu profesor cómo averiguar esto.Otra opción que tienes es descargar la versión de 32 bits, que puede ejecutarse en los dos tipos decomputadoras).

2. Estudia con tu computadora el tutorial de Python, mencionado anteriormente. En otras palabras,ejecuta en tu computadora las instrucciones que se dan en esta sección a la vez que vas leyendo eltutorial. Anota las dudas que tengas para que puedas preguntar más adelante a tu profesor.

8 Capítulo 1. Programación básica

Page 13: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

1.2.2 Práctica 2

• Visita la página http://staff.not.iac.es/~rcardenes/hg/diveintopython3-es/native-datatypes.html y es-tudia los tipos de datos nativos que soporta Python 3 (puedes consultar la versión original en inglésen http://getpython3.com/diveintopython3/native-datatypes.html)

1.3 Expresiones y operadores

1.3.1 Práctica 3

1. Considere el movimiento vertical de una pelota que se lanza al aire. Dicho movimiento está dado porla fórmula

y(t) = v0(t)−1

2gt2 (1.6)

Con ayuda del siguiente bloque de código, verifica la posición de la pelota a los 0.6 segundos de serlanzada, si la velocidad inicial con que fue lanzada es de 6 m/s:

# Program for computing the height of a ball in vertical motion.v0 = 5 # initial velocityg = 9.81 # acceleration of gravityt = 0.6 #timey = v0*t - 0.5*g*t**2 # vertical positionprint(y)

¿Cuáles son los operadores que utilizas para la multiplicación y para la exponenciación?

2. Considere el movimiento vertical de la pelota dado por la ecuación (1.6). ¿Cuánto tiempo le toma a lapelota alcanzar la altura yc?

• Comprueba que las soluciones están dadas por las raíces de la ecuación 1

2gt2 − v0t+ yc = 0

• Usando la fórmula general para encontrar las raíces de una ecuación de segundo grado, compruebaque las soluciones son:

t1 =

(v0 −

√v20 − 2gyc

)/g, t2 =

(v0 +

√v20 − 2gyc

)/g (1.7)

• Utilizando el siguiente bloque de código, averigua cuáles son los dos instantes de tiempo en queuna pelota está a una altura de 0.3 m, si la velocidad inicial de la pelota es de 6 m/s:v0 = 5g = 9.81yc = 0.2import matht1 = (v0 - math.sqrt(v0**2 - 2*g*yc))/gt2 = (v0 + math.sqrt(v0**2 - 2*g*yc))/gprint('En t={0:.4f} s y t={1:.4f} s, la altura es {2:.4f} m.'.format(t1, t2, yc))

3. Revisa los siguientes links

• http://docs.python.org/3/library/numeric.html

• http://docs.python.org/3/library/math.html

1.3. Expresiones y operadores 9

Page 14: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

• Utilizando el siguiente bloque de código, indica cuáles son los valores que toma la variable v:

import math as m# m is now the name of the math modulev = m.sin(m.pi)from math import log as lnv = ln(5)from math import sin as s, cos as c, log as lnv = s(x)*c(x) + ln(x)

4. Con ayuda del siguiente código, calcula las dos raíces complejas de la ecuación cuadrática f(x) =ax2 + bx+ c cuando a = 1, b = 2 y c = 100:

>>> a = 1; b = 2; c = 100 # polynomial coefficients>>> from numpy.lib.scimath import sqrt>>> r1 = (-b + sqrt(b**2 - 4*a*c))/(2*a)>>> r2 = (-b - sqrt(b**2 - 4*a*c))/(2*a)

1.4 Procedimientos y funciones

1.4.1 Práctica 4

1. Introduce la siguiente función en WinPython (o en IDLE, emacs, o el editor de tu preferencia):

def mi_funcion(param1, param2):print param1print param2

2. Llama la función anterior con los argumentos

• 3

• “Hola”

¿Cuál es el tipo de estos argumentos? Utiliza la función type()

3. Convierte de metros a unidades de longitud inglesas. Construye un programa que reciba una longituden metros y que entonces calcule y depliegue la correspondiente longitud en pulgadas, pies y millas.Utiliza las siguientes equivalencias:

• 1 pulgada = 2.54 cm

• 1 pie = 12 pulgadas

• 1 yarda = 3 pies

• 1 milla inglesa = 1760 yardas

Como verificación puede usar los siguientes datos:

• 640 m = 25196.85 pulgadas = 2099.74 pies = 699.91 yardas = 0.3977 millas inglesas

4. Modifica (en caso de ser necesario) el programa del ejercicio anterior de modo que utilices funcionespara resolver el problema propuesto.

5. Basándote en el siguiente código, calcula el área de un paralelogramo, de un cuadrado y de un círculo,así como el volumen de un cono utilizando funciones:

10 Capítulo 1. Programación básica

Page 15: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

from math import pi

h = 5.0 # alturab = 2.0 # baser = 1.5 # radio

area_paralelogramo = h*bprint("El area del paralelogramo es {0:.3f}".format(area_paralelogramo))

area_cuadrado = b**2print("El area del cuadrado es {}".format(area_cuadrado))

area_circulo = pi*r**2print("El area del circulo es {0:.3f}".format(area_circulo))

volumen_cono = 1.0/3*pi*r**2*hprint("El volumen del cono es {0:.3f}".format(volumen_cono))

1.5 Estructuras de control

1.5.1 Estructuras selectivas

Estudia las páginas 29 a 31 del libro “Python para todos”.

Ejemplo 1

Construya un diagrama de flujo (vea la Figura Selección simple (if)) tal que dado como dato la calificaciónde un alumno en un examen, escriba “aprobado” en caso de que esa calificación sea mayor o igual a 70.

Figura 1.2: Selección simple (if)

1.5. Estructuras de control 11

Page 16: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

El siguiente código imprime “Aprobado”:

cal = 80if cal >= 70:

print("Aprobado")

Ejemplo 2

Construya un diagrama de flujo (vea la Figura Selección doble (if else).) tal que dado como dato la calificaciónde un alumno en un examen, escriba “aprobado” si su calificación es mayor o igual a 70 y “reprobado” encaso contrario.

Figura 1.3: Selección doble (if else).

El siguiente código imprime “Reprobado”:

cal = 60if cal >= 70:

print("Aprobado")else:

print("Reprobado")

Ejemplo 3

Construya un diagrama de flujo tal que dado como datos la categoría y el sueldo de un trabajador, calculeel aumento correspondiente teniendo en cuenta la siguiente tabla. Imprima la categoría del trabajador y sunuevo sueldo.

Categoría Aumento1 15%2 10%3 8%4 7%

El siguiente código resuelve el ejemplo:

12 Capítulo 1. Programación básica

Page 17: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

cat = 2sue = 1000

if cat == 1:n_sue = sue * 1.15

elif cat == 2:n_sue = sue * 1.10

elif cat == 3:n_sue = sue * 1.08

else:n_sue = sue * 1.07

print("La categoría del trabajador es {}".format(cat))print("El nuevo sueldo es {}".format(n_sue))

¿Cuál es el salario del trabajador (considerando que el salario actual es de $1000.00) para cada categoría?

Ejercicios

1. Construya un diagrama de flujo tal que dado como dato un número entero, determine e imprima siel mismo es positivo, negativo o cero. Utilice la estructura de selección multiple. Después codifique susolución en Python.

2. En una tienda efectúan un descuento a los clientes dependiendo del monto de la compra. El descuentose efectúa con base en el siguiente criterio:

• Si el monto es menor que $500.00, no hay descuento.

• Si el monto está comprendido entre $500.00 y $1,000.00 (inclusive), 5% de descuento.

• Si el monto está comprendido entre $1,000.00 y $7,000.00 (inclusive), 7% de descuento.

• Si el monto está comprendido entre $7,000.00 y $15,000.00 (inclusive), 11% de descuento.

• Si el monto es mayor a $15,000.00, 18% de descuento.

Construya un diagrama de flujo que ilustre la solución del ejercicio. Después codifique su solución enPython.

3. En un estudio se ha hecho un estudio sobre los pacientes registrados durante los últimos 10 años, conel objeto de hacer una aproximación de los costos de internación por paciente. Se obtuvo un promediodiario según el tipo de enfermedad que aqueja al paciente. Además se pudo determinar que en promediotodos los pacientes con edad entre 14 y 22 años implican un costo adicional del 10%. La siguiente tablaexpresa los costos diarios, según el tipo de enfermedad.

Tipo de enfermedad Costo/paciente/día1 252 163 204 32

Construya un programa en Python que calcule e imprima el costo total que representa un paciente(pista: considere el número de días que el paciente permanece internado).

1.5.2 Estructuras cíclicas

Estudia las páginas 32 a 35 del libro “Python para todos”

1.5. Estructuras de control 13

Page 18: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

Ejemplo 1

Imprima una tabla de conversión de grados Celsius a grados Fahrenheit. Dicha tabla debe verse como lasiguiente:

Celsius Fahrenheit-20 -4.0-15 5.0-10 14.0-5 23.00 32.05 41.010 50.015 59.020 68.025 77.030 86.035 95.040 104.0

El siguiente código resuelve el ejemplo:

print("------------------") # Encabezado de la tablaC = -20 # valor inicial de CdC = 5 # incremento de C en el ciclo

while C <= 40: # mientras C sea menor o igual que 40, hacerF = (9.0/5)*C + 32print("{0}, {1}".format(C, F))C = C + dC

print("------------------") # Fin de la tabla

Podemos construir una lista de las temperaturas con el siguiente código:

Cdegrees = []for C in range(-20, 45, 5):

Cdegrees.append(C)

List Comprehension. Dado que recorrer una lista elemento a elemento y por cada uno de ellos crear otronuevo en una lista distinta es una tarea frecuente, Python tiene una sintaxis compacta para hacer esto,llamada list comprehension. La sintaxis general es:

new_list = [E(e) for e in list]

donde E(e) representa una expresión que envuelve al elemento e. A continuación ponemos varios ejemplos:

Cdegrees = [-5 + i*0.5 for i in range(n)]Fdegrees = [(9.0/5)*C + 32 for C in Cdegrees]

La tabla anterior puede construirse con un ciclo for:

table = []for C, F in zip(Cdegrees, Fdegrees):

table.append([C, F])

Una versión más pythonica del ciclo anterior se consigue utilizando una list comprehension:

14 Capítulo 1. Programación básica

Page 19: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

table = [[C, F] for C, F in zip(Cdegrees, Fdegrees)]

Ejemplo 2

Las sumatorias ocurren con frecuencia en las matemáticas. Por ejemplo, la función sin(x) puede calcularsecomo un polinomio:

sin(x) ≈ x− x3

3!+

x5

5!− x7

7!+ · · · (1.8)

donde 3! = 3·2·1, 5! = 5·4·3·2·1, etc. son factoriales. La expresión k! puede calcularse con math.factorial(k).

Se requiere de un número infinito de términos en el lado derecho de (1.8) para que sea válido usar el signode igualdad. Con un número finito de términos, se obtiene una aproximación de la función sin(x).

Suponga que es necesario calcular el lado derecho de (1.8) para potencias de hasta N = 25. El cálculo de lasuma anterior con un ciclo while de Python, utiliza lo siguiente:

1. Un contador k que toma los valores impares desde 1 hasta un algún número máximo N.

2. Una variable para la sumatoria, digamos sumatoria, que acumule los términos, uno a la vez.

El propósito de cada iteración del ciclo es calcular un nuevo término y añadirlo a sumatoria. Dado que elsigno de cada término se alterna, podemos introducir una variable signo que cambie entre −1 y 1 en cadaiteración del ciclo.

Las ideas anteriores pueden codificarse en Python de la siguiente manera:

x = 1.2 # asignar algún valorN = 25 # maxima potencia en la sumak = 1sumatoria = xsigno = 1.0import math

while k < N:signo = - signok = k + 2term = signo * x**k / math.factorial(k)sumatoria = sumatoria + term

print("sin({0:g}) = {1:g} (aproximación con N = {2:d})".format(x, sumatoria, N))print("Valor real = {0:g}".format(math.sin(x)))

Ejemplo 3: Series de Fourier

Sea f(t) una función definida en un intervalo (a, a + T ), donde a ∈ R y T > 0 es el periodo de la función.f(t) puede escribirse como

f(t) =a02

+

∞∑n=1

[an cos

(2nπt

T

)+ bn sin

(2nπt

T

)]

1.5. Estructuras de control 15

Page 20: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

Para encontrar los coeficientes a0, an y bn, se utilizan las siguientes fórmulas:

a0 =2

T

∫ a+T

a

f(t) dt

an =2

T

∫ a+T

a

f(t) cos(2nπt

T

)dt

bn =2

T

∫ a+T

a

f(t) sin(2nπt

T

)dt

El uso más frecuente de la serie de Fourier es para representar funciones periódicas. Lo que se hace es definirla función para un intervalo (a, a+T ) con una serie de Fourier. El resultado es una función definida en todoel eje real.

El valor a02

siempre da el valor promedio de la función. El valor que da la serie geométrica de Fourier paralos valores en que la función presenta discontinuidades es el valor promedio de la función.

Un desarrollo en serie de Fourier para f(t) definida de acuerdo con la figura

import matplotlib.pyplot as pltimport numpy as npx1 = np.array([0.0, 1.0])y1 = np.array([2.0, 2.0])x2 = np.array([1.0, 2.0])y2 = np.array([-1.0, -1.0])plt.plot(x1, y1, 'b', x2, y2, 'b')plt.axis([0.0, 2.0, -2.0, 3.0])plt.grid()plt.show()

16 Capítulo 1. Programación básica

Page 21: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

0.0 0.5 1.0 1.5 2.02

1

0

1

2

3

está dado por las siguientes expresiones:

a0 = 1

an = 0

bn =3

nπ[1− (−1)

n]

T = 2

es decir, la solución es:

f(t) =1

2+

∞∑n=1

3

nπ[1− (−1)

n] sin(nπt)

=1

2+

∞∑n=1

6

(2n− 1)πsin [(2n− 1)πt]

=1

2+

6

π

∞∑n=1

sin [(2n− 1)πt]

2n− 1

La gráfica siguiente se obtiene utilizando los primeros 3 términos de la sumatoria de la última expresión paraf(t):

import matplotlib.pyplot as pltimport numpy as npfrom numpy import pi

1.5. Estructuras de control 17

Page 22: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

num_puntos = 301t = np.linspace(-2.0, 4.0, num_puntos)f = np.zeros((3, num_puntos))for n in range(3):

impar = 2*n + 1theta = impar*pi*tf[n] = np.sin(theta)/imparplt.plot(t, f[n])

y = 0.5 + 6.0/pi*f.sum(0)plt.plot(t, y)plt.grid()plt.show()

2 1 0 1 2 3 41.5

1.0

0.5

0.0

0.5

1.0

1.5

2.0

2.5

Modifique el programa anterior para visualizar la señal periódica que se obtiene al sumar los primeros dieztérminos de la serie. Después visualize la señal correspondiente a 100 términos.

Ejercicios

1. Escriba un programa que genere todos los números impares desde 1 hasta n. Fije un valor para n alinicio del programa y use un ciclo while para calcular los números. Asegúrese de que si n es un númeropar, el número impar más grande generado es n - 1. Nombre del programa: impar.py

2. Modifique el programa del ejercicio 1 y almacene los números impares generados en una lista. Empiececon una lista vacía y use un ciclo while donde en cada iteración del ciclo agregue un nuevo elemento a la

18 Capítulo 1. Programación básica

Page 23: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

lista. Finalmente, imprima la lista de elementos en la pantalla. Nombre del programa: lista_impares1.py

3. Resuelva el ejercicio 2 utilizando una list comprehension (con for y range). Nombre del programa:lista_impares2.py

4. (Calculo de una sumatoria) Se supone que el siguiente código calcule la suma s =M∑k=1

1

k:

s = 0k = 1M = 100while k < M:

s += 1/kprint(s)

Este programa no funciona correctamente. ¿Cuáles son los tres errores? Si usted intenta ejecutar elprograma, nada sucederá en la pantalla. Teclee Ctrl-C, es decir, presione (y deje presionada) la teclaControl (Ctrl) y entonces teclee la letra c, para detener el programa. Escriba un programa correcto.Nombre del programa: suma_while.py.

Hay dos formas básicas de encontrar errores en el programa:

(a) Lea el programa cuidadosamente y piense en las consecuencias de cada instrucción

(b) Imprima resultados intermedios y compare con los cálculos manuales

Primero, intente el método (a) y encuentre tantos errores como pueda. Entonces, intente el método (b)para M = 3 y compare la evolución de s con sus propios cálculos manuales.

Nota: Una forma pythonica de resolver este problema es mediante:

print(sum(1.0/k for k in xrange(1, M+1, 1)))

5. El siguiente programa grafica la función trigonométrica sin(x)

import matplotlib.pyplot as pltimport numpy as npfrom numpy import pix = np.linspace(-2*pi, 2*pi, 101)y = np.sin(x)plt.plot(x, y)plt.grid()plt.show()

1.5. Estructuras de control 19

Page 24: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

8 6 4 2 0 2 4 6 81.0

0.5

0.0

0.5

1.0

Suponga que desea calcular la función seno inversa: arcsin(x). El módulo numpy tiene una función paracalcular dicha función, ¿pero cuál es el nombre de esta función? Grafique esta función en el dominioadecuado.

6. Sea:

q = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h']]

Indexe esta lista para extraer

(a) La letra a

(b) La lista ['d', 'e', 'f']

(c) El último elemento h

(d) El elemento d

(e) Explique por qué q[-1][-2] tiene el valor g.

Nombre del programa: index_nested_list.py

7. Construya un doble loop sobre una lista anidada. Considere la lista del ejercicio 6. Es posible visitartodos los elementos de q usando el siguiente for loop anidado:

for i in q:for j in range(len(i)):

print i[j]

¿Cuál es el tipo de las variables i y j?

20 Capítulo 1. Programación básica

Page 25: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

8. Reescriba la generación de la lista anidada q:

q = [r**2 for r in [10**i for i in range(5)]]

utilizando ciclos estándar for en lugar de list comprehensions.

9. Grafique la siguiente función utilizando matplotlib

N(x) =

0 si x < 0

x si 0 ≤ x < 1

2− x si 1 ≤ x < 2

0 si x ≥ 2

10. Un desarrollo en serie de Fourier para la función dada por:

f(t) =

0, si 0 < t <π

2

t− π

2, si π

2< t < π

2− t, si π < t <

2

0, si 3π

2< t < 2π

donde el periodo es T = 2π, está dado por:

a0 =π

4

an =2

n2π

[(−1)

n − cos(nπ

2

)]bn = 0

es decir, la solución es:

f(t) =π

8+

∞∑n=1

2

n2π

[(−1)

n − cos(nπ

2

)]cos(nt)

8+

2

π

∞∑n=1

1

n2

[(−1)

n − cos(nπ

2

)]cos(nt)

Grafique la serie anterior con 100 términos.

1.5. Estructuras de control 21

Page 26: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

22 Capítulo 1. Programación básica

Page 27: Anal is is Numeric o Con Python

CAPÍTULO 2

Gráficas

2.1 Gráficas simples

La visualización de una curva f(x) se realiza al graficar lineas rectas entre n puntos en la curva. Entre máspuntos se usen, más suave es la forma de la gráfica. Com ejemplo, vamos a graficar la curva y = t2e−t2 paravalores de t entre 0 y 3. Primero generamos coordenadas igualmente espaciadas para t, para este ejemplo,51 valores (50 intervalos). Entonces calculamos los correspondientes valores para y en estos puntos, antes deinvocar el comando plot(t, y) para obtener la gráfica. A continuación mostramos el programa:

from matplotlib.pylab import *

def f(t):return t**2*exp(-t**2)

t = linspace(0, 3, 51) # 51 puntos entre 0 y 3y = zeros(len(t)) # reservar espacio de memoria para y con elementos flotantes.

# Se puede hacer utilizando ciclos, pero es mas lento# for i in xrange(len(t)):# y[i] = f(t[i])

# Se obtiene una ejecucion mas rapida (y la sintaxis tambien es mas simple)# actuando sobre todo el arreglo ty = f(t)

plot(t, y)xlabel("t")ylabel("y")legend(["t^2*exp(t^2)"])show()

23

Page 28: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

0.0 0.5 1.0 1.5 2.0 2.5 3.0t

0.00

0.05

0.10

0.15

0.20

0.25

0.30

0.35

0.40y

t^2*exp(t^2)

Descarga el manual de matplotlib de http://matplotlib.org/contents.html (o use directamente el linkhttp://matplotlib.org/Matplotlib.pdf) y estudia el tutorial de pyplot.

1. Grafica la función f(x) = x3 en color rojo, con líneas punteadas, en el intervalo de −5 a 5.

2. Modifica el grueso de la línea de la gráfica anterior a 2.0.

3. Grafica las funciones seno y coseno en el rango de [−π, π] utilizando el comando subplot()

2.1.1 La función exponencial

En 1840 P.F. Verhulst, matemático y biólogo belga, propuso un modelo para predecir el crecimiento depoblaciones humanas. La llamada función logística

P (t) =K

1 + cert, r < 0 (2.1)

donde k, c y r son constantes, ha demostrado ser un modelo exacto de crecimiento para poblaciones deprotozoarios, bacterias, moscas de fruta o animales confinados a espacios limitados. Este modelo muestraun crecimiento acotado. Más específicamente, la problación predicha por (2.1) no aumentará más allá delnúmero K, llamado capacidad límite o de soporte del sistema. Para r < 0, ert → 0 y P (t) → 0 cuandot → ∞.

24 Capítulo 2. Gráficas

Page 29: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

2.1.2 Práctica 5

Un alumno enfermo de un virus de catarro regresa a un colegio aislado, de 2 000 estudiantes. La cantidad deestudiantes infectados con catarro, t días después del regreso del alumno enfermo, se calcula con la funciónlogística

P (t) =2000

1 + 1999e−0.8905t

1. De acuerdo con este modelo, ¿cuántos estudiantes serán infectados por el catarro después de 5 días?

Para responder a esta pregunta, basta con calcular P (5) = 82.348 (en realidad son 83 estudiantes).Esto cálculo puede hacerse con una calculadora, o con el siguiente código:

import numpy as npdef p(t):

return 2000.0/(1.0 + 1999.0*np.exp(-0.8905*t))print(p(5))

2. ¿Cuánto tiempo pasará para que la mitad de la población de estudiantes quede infectada?

Para responder a esta pregunta de manera exacta, se puede despejar t de la ecuación:

1000 =2000

1 + 1999e−0.88905t

cuya solución es t = ln(1999)/0.8905 ≈ 8.535 días. Esto puede responderse de manera aproximadautilizando una gráfica.

3. ¿Cuántos alumnos indica el modelo que se infectarán después de un tiempo muy prolongado?

El modelo indica que se infectarán todos los estudiantes.

4. Trace una gráfica de P (t).

import matplotlib.pyplot as pltimport numpy as npt = np.linspace(0.0, 20.0, 2001)p = 2000.0/(1.0 + 1999.0*np.exp(-0.8905*t))plt.plot(t, p)plt.grid()fig = plt.gcf()size = fig.get_size_inches()scale = 0.6fig.set_size_inches( (size[0]*scale, size[1]*scale) )plt.show()

2.1. Gráficas simples 25

Page 30: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

0 5 10 15 200

500

1000

1500

2000

Ahora veremos la misma gráfica con una escala logarítmica en el eje vertical:

import matplotlib.pyplot as pltimport numpy as npt = np.linspace(0.0, 20.0, 2001)p = 2000.0/(1.0 + 1999.0*np.exp(-0.8905*t))plt.semilogy(t, p)plt.grid()fig = plt.gcf()size = fig.get_size_inches()scale = 0.6fig.set_size_inches( (size[0]*scale, size[1]*scale) )plt.show()

26 Capítulo 2. Gráficas

Page 31: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

0 5 10 15 20100

101

102

103

104

2.2 Gráficas de contorno

Utilizando el código siguiente, trate de reproducir la figura siguiente

import numpy as npimport matplotlib.pylab as pl

def f(x, y):return (1 - x/2 + x**5 + y**3) * np.exp(-x**2 - y**2)

n = 256x = np.linspace(-3, 3, n)y = np.linspace(-3, 3, n)X, Y = np.meshgrid(x, y)pl.contourf(X, Y, f(X, Y), 8, alpha=0.75, cmap='jet')C = pl.contour(X, Y, f(X, Y), 8, colors='black', linewidth=0.5)pl.show()

2.2. Gráficas de contorno 27

Page 32: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

3 2 1 0 1 2 33

2

1

0

1

2

3

2.3 Gráficas en 3D

2.3.1 Práctica 6

(surface3ddemo.py)

from mpl_toolkits.mplot3d import Axes3Dfrom matplotlib import cmfrom matplotlib.ticker import LinearLocator, FormatStrFormatterimport matplotlib.pyplot as pltimport numpy as np

fig = plt.figure()ax = fig.gca(projection='3d')X = np.arange(-5, 5, 0.25)Y = np.arange(-5, 5, 0.25)X, Y = np.meshgrid(X, Y)R = np.sqrt(X**2 + Y**2)Z = np.sin(R)surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False)ax.set_zlim(-1.01, 1.01)

ax.zaxis.set_major_locator(LinearLocator(10))

28 Capítulo 2. Gráficas

Page 33: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()

64

20

24

6 64

20

24

6

-1.01-0.79-0.56-0.34

-0.11

0.11

0.34

0.56

0.79

1.01

0.80.60.40.2

0.00.20.40.60.8

2.4 Ejercicios

1. Conducción electrolítica en las rocas (Ley de Archie). La resistividad eléctrica de un cilíndrosólido de longitud L y sección transversal A, con resistencia R entre sus dos caras, está dado por:

ρ = RA

L

Debido a que la mayoría de las rocas son pobres conductores, sus resistidades serían muy grandes si nofuera por el hecho de que son usualmente porosas y que los poros están llenos con fluidos, principalmenteagua. Como resultado, las rocas son conductores electrolíticos, cuya resistividad efectiva puede definirsepor la fórmula anterior, donde la propagación de la corriente se da mediante conducción iónica (pormoléculas que tienen un exceso o deficiencia de electrones). Por lo tanto la resistividad varía con lamovilidad, concentración y grado de disociación de los iones (esta última depende de la constantedieléctrica del solvente). El flujo de corriente no solamente es lento comparado con la conducciónohmica, sino que implica un transporte real de material, normalmente resultando en transformaciónquímica.

2.4. Ejercicios 29

Page 34: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

La conductividad de una roca porosa varía con el volumen y el arreglo de los poros y más aún conla conductividad y la cantidad de agua contenida. De acuerdo con la fórmula empírica obtenida porArchie (1942):

ρe = aϕ−mS−nρW

donde ϕ es la fracción de volumen poroso (porosidad), S es la fracción de los poros que contienen agua,ρW es la resistividad del agua, n ≈ 2 y a, m son constantes, 0.5 ≤ a ≤ 2.5, 1.3 ≤ a ≤ 2.5.

Suponga que S = 1, a = 1.5 y m = 2, entonces

ρeρW

=1.5

ϕ2

Utilice una gráfica con escalas logarítmicas para graficar la fórmula anterior para valores de ϕ = 0.01,0.1, 0.3, 0.5.

2. Vida media del plutonio. Un reactor de cría convierte uranio 238 relativamente estable en el isótopoplutonio 239. Después de 15 años, se ha determinado que 0.043% de la cantidad inicial de A0 de plutoniose ha desintegrado.

(a) Determine la vida media de ese isótopo, si la razón de desintegración es proporcional a la cantidadque queda.

(b) Grafique A(t) si A0 = 1.0 kg. Verifique gráficamente la respuesta del inciso anterior.

2.5 Gráficas de algunos campos simples

Revisemos varias representaciones del campo vectorial

A = cos(x)ı+ sin(y)ȷ

La siguiente figura utiliza flechas para indicar la dirección del campo. El color indica la magnitud del campo.

from pylab import *from numpy import ma

X,Y = meshgrid( arange(0,2*pi,.2),arange(0,2*pi,.2) )U = cos(X)V = sin(Y)

figure()M = sqrt(pow(U, 2) + pow(V, 2))Q = quiver( X, Y, U, V, M)qk = quiverkey(Q, 0.5, 0.92, 2, r'$2 \frac{m}{s}$', labelpos='W', \

fontproperties={'weight': 'bold'})l, r, b, t = axis()dx, dy = r - l, t - baxis([l - 0.05*dx, r + 0.05*dx, b - 0.05*dy, t + 0.05*dy])colorbar()show()

30 Capítulo 2. Gráficas

Page 35: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

2ms

0 1 2 3 4 5 6 7

0

1

2

3

4

5

6

7

0.15

0.30

0.45

0.60

0.75

0.90

1.05

1.20

1.35

Ahora se utilizan líneas de fuerza para indicar la dirección de campo. El color está asociado a la magnituddel campo.

import numpy as npfrom numpy import piimport matplotlib.pyplot as plt

Y, X = np.mgrid[0:2*pi:100j, 0:2*pi:100j]U = np.cos(X)V = np.sin(Y)M = np.sqrt(U*U + V*V)

plt.streamplot(X, Y, U, V, color=M, linewidth=2, cmap=plt.cm.autumn)plt.colorbar()plt.show()

2.5. Gráficas de algunos campos simples 31

Page 36: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

0 1 2 3 4 5 60

1

2

3

4

5

6

0.15

0.30

0.45

0.60

0.75

0.90

1.05

1.20

1.35

2.5.1 Ejercicio

Representa el campo vectorial siguiente de las dos maneras ejemplificadas anteriormente.

A = sin(π2y)ı− sin

(π2x)ȷ

32 Capítulo 2. Gráficas

Page 37: Anal is is Numeric o Con Python

CAPÍTULO 3

Álgebra lineal

3.1 Arreglos de NumPy

Numpy es el paquete fundamental para cómputo científico en Python. Se trata de una librería para Pythonque proporciona un arreglo multidimensional, varios objetos derivados (tales como arreglos enmascarados ymatrices), y varias rutinas para operaciones rápidas sobre arreglos, incluyendo manipulación matemática,lógica y de la “forma” de los arreglos; ordenamiento, selección, I/O, transformadas discretas de Fourier,álgebra lineal básica, operaciones estadísticas básicas, simulación aleatoria y mucho más.

Para ilustrar la importancia de los arreglos de NumPy, considere el siguiente problema: multiplicar cadaelemento de una secuencia unidimensional con el correspondiente elemento de otra secuencia de la mismalongitud. Si los datos están almacenados en dos listas de Python, a y b, podríamos iterar sobre cada elemento,de la siguiente manera:

c = []for i in range(len(a)):

c.append(a[i]*b[i])

Esto produce el resultado correcto, pero si a y b contienen cada uno un millón de números, pagaremos elprecio por las ineficiencias de los ciclos en Python. Podríamos conseguir la misma tarea mucho más rápidoen C al escribir (por simplicidad no escribimos las declaraciones de variables, inicializaciones, la reservacióndel espacio de memoria, etc.).

for (i = 0; i < numero_elementos; i++) {c[i] = a[i]*b[i];

}

Utilizando arreglos de Numpy a y b, podemos realizar la misma operación con:

c = a * b

casi a la misma velocidad que con C, pero con la simplicidad en la programación que se espera de códigoescrito en Python.

3.1.1 Un ejemplo más realista en C

El siguiente ejemplo muestra el producto punto de dos vectores en C (se está utilizando el framework“Accelerate”, específico para Mac OS X, que incluye una librería para BLAS, es decir “Basic Linear Algebra”)

33

Page 38: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

#include <stdio.h>#include <stdlib.h>#include <Accelerate/Accelerate.h>

void runSDOTSample (void) {float *X, *Y;int N, i;float resultFloat;

// Initialize the inputs and allocate spaceN = 10;X = ( float* ) malloc ( sizeof ( float ) * N );Y = ( float* ) malloc ( sizeof ( float ) * N );

for ( i = 0; i < N; i++ ) {X[i] = 1.0;Y[i] = 2.0;

}resultFloat = cblas_sdot ( N, X, 1, Y, 1 );printf("the result of cblas_sdot is %4.4f\n", resultFloat);//deallocate spacefree ( X );free ( Y );

}

int main(int argc, const char * argv[]) {runSDOTSample();return 0;

}

3.1.2 Práctica 4

Imagine que desea sumar dos vectores llamados a y b. El vector a contiene los cuadrados de los enteros 0hasta n (excluyendo n); por ejemplo, si n = 3, entonces a = (0, 1, 4). El vector b contiene los cubos de losenteros 0 hasta n (excluyendo n); por ejemplo, si n = 3, entonces b = (0, 1, 8). ¿Cómo haría eso con Pythonúnicamente?

Sumando vectores utilizando Python “puro”

La siguiente función resuelve el problema de la suma de vectores utilizando Python sin NumPy:

def pythonsum(n):a = range(n)b = range(n)c = []for i in range(len(a)):

a[i] = i ** 2b[i] = i ** 3c.append(a[i] + b[i])

return c

Sumando vectores utilizando NumPy

La siguiente función resuelve el mismo problema con NumPy:

34 Capítulo 3. Álgebra lineal

Page 39: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

def numpysum(n):a = numpy.arange(n) ** 2b = numpy.arange(n) ** 3c = a + breturn c

Comparando los tiempos de ejecución

Con ayuda del siguiente código, compare los tiempos de ejecución para n = 1000, 2000, 3000.

• Ejecute su programa desde la línea de comandos.

import sysfrom datetime import datetimeimport numpy

def numpysum(n):a = numpy.arange(n) ** 2b = numpy.arange(n) ** 3c = a + breturn c

def pythonsum(n):a = range(n)b = range(n)c = []for i in range(len(a)):

a[i] = i ** 2b[i] = i ** 3c.append(a[i] + b[i])return c

size = int(sys.argv[1])start = datetime.now()c = pythonsum(size)delta = datetime.now() - startprint("The last 2 elements of the sum {}".format(c[-2:]))print("PythonSum elapsed time in microseconds {}".format(delta.microseconds))start = datetime.now()c = numpysum(size)delta = datetime.now() - startprint("The last 2 elements of the sum {}".format(c[-2:]))print("NumPySum elapsed time in microseconds {}".format(delta.microseconds))

Este programa funciona adecuadamente con Python de 64 bits. La tabla siguiente muestra los tiempos deejecución (en microsegundos) obtenidos en mi máquina para algunos valores de size (la segunda columnacorresponde a la función que utiliza listas y la tercera, a la función que utiliza arreglos de NumPy):

size Tiempo (pythonsum) Tiempo (numpysum)10 20 50100 66 521000 622 7810000 5468 369

3.1. Arreglos de NumPy 35

Page 40: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

3.1.3 Arreglos multidimensionales

Los arreglos de NumPy son homogéneos, es decir, los elementos del arreglo tienen que ser del mismo tipo.La ventaja es que ahora es fácil determinar el tamaño que se requiere para almacenar el arreglo. Los arreglosde NumPy se indexan como en Python, a partir de 0.

Utilizando el siguiente código, averigüe cuál es el tipo de los elementos del arreglo a (las respuestas sondiferentes dependiendo de si utiliza Python de 32 bits o de 64 bits):

>>> a = arange(5)>>> a.dtype

Además del tipo de los elementos del arreglo, también es importante conocer su “forma”:>>> a>>> array([0, 1, 2, 3, 4])>>> a.shape>>> (5,)

El atributo shape (forma) del arreglo es una tupla, en este caso, una tupla de 1 elemento, que contiene eltamaño del arreglo en cada dimensión.

Creando un arreglo multidimensional

Muestre la forma y el tipo de los elementos del arreglos siguientes:

>>> m1 = array([arange(2), arange(2)])>>> m2 = array([ [1, 2], [3, 4] ])

Ahora cree una matriz de tamaño 3× 3 con los siguientes elementos0 1 23 4 56 7 8

Compruebe que también puede crearlo de la siguiente manera:

>>> m3 = arange(9).reshape(3, 3)

Los elementos de m3 pueden accederse mediante la siguiente sintáxis:

>>> m3[0, 0]

¿Cuál es la salida de m3[2, 1]?

3.2 Álgebra Lineal básica con NumPy

El paquete numpy.linalg contiene funciones de álgebra lineal. Con este módulo, usted puede invertir matrices,calcular eigen–valores, resolver sistemas de ecuaciones lineales, calcular determinantes, entre otras cosas.

36 Capítulo 3. Álgebra lineal

Page 41: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

3.2.1 La inversa de una matriz

La inversa de una matriz cuadrada A de n × n se denota por A−1, que cuando se multiplica por la matrizoriginal, es igual a la matriz identidad. Esto puede escribirse como se indica a continuación:

AA−1 = In A−1A = In

La función inv del paquete numpy.linalg puede invertir una matriz por nosotros. Vamos a resolver un ejemplo:

1. Crea la matriz A con la función mat:

>>> A = numpy.mat("0 1 2; 1 0 3; 4 -3 8")

2. Invierte la matriz A con la función inv:

>>> A_inv = numpy.linalg.inv(A)

Si la matriz es singular, o no es cuadrada, resulta un error LinAlgError.

3. Verifica utilizando multiplicación matricial:

>>> print("Verifica\n {}".format(A * A_inv))

3.2.2 Resolviendo un sistema de ecuaciones lineales

La función solve de numpy.linalg resuelve sistemas de ecuaciones de la forma Ax = b, donde A es unamatriz, b puede ser un arreglo unidimensional o bidimensional, y x es la variable desconocida.

1. Crea la matriz A y el vector b:

>>> A = numpy.mat("1 -2 1; 0 2 -8; -4 5 9")>>> print("A\n {}".format(A))>>> b = numpy.array([0, -8, 9])>>> print("b\n {}".format(b))

2. Invoque la función solve para resolver el sistema de ecuaciones lineales:

>>> x = numpy.linalg.solve(A, b)>>> print("Solucion: {}".format(x))

3. Verifique que la solución es correcta (dot realiza una multiplicación matricial):

>>> print("Verifica\n {}".format( numpy.dot(A, x) ))

3.3 Ejercicios

Instrucciones: Utilice Numpy para resolver los siguientes ejercicios.

1. Resuelva las operaciones indicadas, suponiendo que u =

3.2−0.6−1.4

, v =

1.54.1−0.2

(a) u · v

(b) ∥u∥

(c) 3v − u

3.3. Ejercicios 37

Page 42: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

(d) u× v

2. Encuentre la solución del sistema de ecuaciones lineales dado por las matrices aumentadas

(a)

0 2 3 82 3 1 51 −1 −2 −5

(b)

1 1 1 1 41 2 3 4 101 3 6 10 201 4 10 20 35

3. Utilice la función numpy.linalg.eig para encontrar los eigenvalores y eigenvectores de la matriz cua-

drada A =

1 0 23 −1 32 0 1

38 Capítulo 3. Álgebra lineal

Page 43: Anal is is Numeric o Con Python

CAPÍTULO 4

Polinomios e interpolación

4.1 Introducción a la Interpolación

La interpolación se usa para estimar valores intermedios entre datos precisos. El método más común quese usa para este propósito es la interpolación polinomial. Para n + 1 puntos, hay uno y sólo un polinomiode orden n que pasa a través de todos los puntos. Por ejemplo, hay sólo una línea recta (un polinomio deprimer orden) que conecta dos puntos. De manera similar únicamente una parábola conecta un conjunto detres puntos. La interpolación polinomial consiste en determinar el único polinomio de n–ésimo orden queajuste n+ 1 puntos. Este polinomio entonces proporciona una fórmula para calcular valores intermedios.

4.1.1 Interpolación de polinomios de Lagrange con SciPy

4.1.2 Ejemplo

Estime log10 5 mediante interpolación lineal.

• Interpole entre log 4 = 0.60206 y log 6 = 0.7781513:

import numpy as npfrom scipy.interpolate import lagrangex = np.array([4.0, 6.0])y = np.array([0.60206, 0.7781513])p = lagrange(x, y)print(p)print(p(4.0))print(p(6.0))print(p(5.0))

• Interpole entre log 4.5 = 0.6532125 y log 5.5 = 0.7403627.

• Ajuste con un polinomio de interpolación de Lagrange de tercer orden para estimar log 5 utilizando losdatos anteriores.

39

Page 44: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

4.1.3 El fenómeno de Runge

Ejemplo

Consideremos el polinomio interpolador de Lagrange de la función f(x) = 1/(1+12x2) en el intervalo [−1, 1]para nodos equiespaciados, ¿tiende a cero el error EN (x) = F (x)− PN (x) cuando N crece? No: el máximodel término del error EN (x) crece cuando N → ∞. Esta falta de convergencia se conoce como fenómenode Runge

import numpy as npimport matplotlib.pyplot as pltfrom scipy.interpolate import lagrange

def f(x):return 1.0/(1.0 + 12.0 * x**2)

x = np.linspace(-1.0, 1.0, 200)plt.plot(x, f(x), '--')

x2 = np.linspace(-1.0, 1.0, 11)p = lagrange(x2, f(x2))

y2 = p(x2)plt.plot(x2, y2, 'o')plt.plot(x, p(x), linewidth=2.0)

plt.grid()plt.show()

Una mejor solución utilizando polinomios de Chebyshev

import numpy as npimport matplotlib.pyplot as pltfrom numpy.polynomial import Chebyshev as T

def f(x):return 1.0/(1.0 + 12.0 * x**2)

N = 11x = np.cos([(2*k + 1)*np.pi/2.0/N for k in range(N)])y = f(x)p = T.fit(x, y, 10)xx, yy = p.linspace()plt.plot(xx, f(xx), '--')plt.plot(x, y, 'o')plt.plot(xx, yy, lw=2)plt.grid()plt.show()

40 Capítulo 4. Polinomios e interpolación

Page 45: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

1.0 0.5 0.0 0.5 1.00.0

0.2

0.4

0.6

0.8

1.0

4.2 Interpolación segmentaria (splines)

4.2. Interpolación segmentaria (splines) 41

Page 46: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

42 Capítulo 4. Polinomios e interpolación

Page 47: Anal is is Numeric o Con Python

CAPÍTULO 5

Ajuste de funciones

Veremos ajuste por mínimos cuadrados.

5.1 Regresión por mínimos cuadrados

5.1.1 Regresión lineal

Es el ajuste de un conjunto de pares de observaciones: (x1, y1), (x2, y2), ldots, (xn, yn) a una línea recta. Laexpresión matemática para esta última es:

y = a0 + a1x+ e

donde a0 y a1 son coeficientes que representan el intercepto y la pendiente, respectivamente, y e es el error,o residuo, entre el modelo y las observaciones, el cual se puede representar al reordenar la expresión anteriorcomo:

e = y − a0 − a1x (5.1)

Así, el error o residuo es la discrepancia entre el valor real de y y el valor aproximado, a0 + a1x, predichopor la ecuación lineal.

En la regresión lineal por mínimos cuadrados, la estrategia es (como su nombre lo indica), minimizar la sumade los cuadrados de los residuos entre la y medida y la y calculada con el modelo lineal:

Sr =n∑

i=1

e2i =n∑

i=1

(yi − a0 − a1xi)2 (5.2)

donde n es el número de pares de observaciones.

Ecuaciones normales (regresión lineal)

Para determinar los valores de a0 y a1 que minimizan la Ec. (5.2), esta última es diferenciada parcialmentecon respecto a cada coeficiente e igualando cada expresión resultante a cero. Como resultado se tienen las

43

Page 48: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

ecuaciones normales:

na0 +(∑

xi

)a1 =

∑yi (5.3)(∑

xi

)a0 +

(∑x2i

)a1 =

∑xiyi (5.4)

que pueden resolverse en forma simultánea.

5.1.2 Ejemplo 1: Lo básico

Ajustemos una línea recta y = mx+ b, a través de unos puntos con un poco de ruido:

import numpy as npx = np.array([ 0, 1, 2, 3])y = np.array([-1, 0.2, 0.9, 2.1])

# Es posible escribir la ecuación lineal como y = Ap, donde# A = [[x 1]]A = np.vstack([x, np.ones(len(x))]).Tprint(A)# y# p = [[m], [b]]# Use np.linalg.lstsq para calcular p:m, b = np.linalg.lstsq(A, y)[0]print(m, b)# Comprueba que# m = 1.0 y b = -0.95

Ahora vamos a graficar los datos junto con la línea ajustada:

import matplotlib.pyplot as pltimport numpy as npx = np.array([ 0, 1, 2, 3])y = np.array([-1, 0.2, 0.9, 2.1])

m, b = 1.0, -0.95plt.plot(x, y, 'o', label='Datos originales', markersize=10)plt.plot(x, m*x + b, 'r', label='Datos ajustados')plt.legend(loc='best')plt.show()

44 Capítulo 5. Ajuste de funciones

Page 49: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

0.0 0.5 1.0 1.5 2.0 2.5 3.01.0

0.5

0.0

0.5

1.0

1.5

2.0

2.5

Datos originalesDatos ajustados

Resuelva el ejercicio manualmente y compruebe sus resultados.

5.1.3 Forma general lineal por mínimos cuadrados

La regresión lineal, polinomial y lineal múltiple pertenecen al siguiente modelo general de mínimos cuadradoslineales:

y = a0z0 + a1z1 + a2z2 + · · ·+ amzm + e (5.5)

donde z0, z1, . . ., zm son las m+1 funciones diferentes. La regresión lineal simple y múltiple encajan dentrode este modelo: z0 = 1, z1 = x1, . . ., zm = xm. Además la regresión de polinomios se incluye también si lasz son monomios simples como en z0 = x0 = 1, z1 = x, . . ., zm = xm.

Observe que la terminología lineal se refiere sólo a la dependencia del modelo sobre sus parámetros (es decir,las a). Como en el caso de regresión de polinomios, las mismas funciones pueden ser altamente no lineales.

La ecuación (5.5) puede se puede expresar en notación matricial como:

Y = ZA+ E (5.6)

donde Z es una matriz d los valores calculados de las funciones z en los valores medidos de las variables

5.1. Regresión por mínimos cuadrados 45

Page 50: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

independientes

Z =

z01 z11 · · · zm1

z02 z12 · · · zm2

...... . . . ...

z0n z1n · · · zmn

donde m es el número de variables del modelo y n es el número de datos. Como n ≥ m + 1, la mayoría delas veces Z no es una matriz cuadrada.

El vector columna Y contiene los valores observados de la variable dependiente:

Y =

y1y2...yn

El vector columna A contiene los coeficientes desconocidos

A =

a0a1...

am

y el vector columna E contiene los residuos

E =

e1e2...an

La suma de los cuadrados de los residuos para este modelo se puede definir como

Sr =n∑

i=1

e2i =n∑

i=1

yi −m∑j=0

ajzji

2

Esta cantidad se puede minimizar al tomar su derivada parcial con respecto a cada uno de los coeficientes yfijar los resultados de la ecuación igual a cero. La salida de este proceso son las ecuaciones normales quese pueden expresar brevemente en forma de matriz como

ZTZA = ZTY (5.7)

Ejemplo 2: Regresión polinomial (de segundo orden)

Ajustar a una parábola los datos siguientes:

46 Capítulo 5. Ajuste de funciones

Page 51: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

xi yi0 2.11 7.72 13.63 27.24 40.95 61.1

La matriz Z debe tomar la forma

Z =

1 x1 x2

1

1 x2 x22

......

...1 xn x2

n

(5.8)

que es un caso particular de la matriz de Vandermonde

Z =

1 x1 x2

1 · · · xm1

1 x2 x22 · · · xm

2...

......

...1 xn x2

n · · · xmn

Podemos definir una función en python que calcule la matriz de Vandermonde de la siguiente manera:

import numpy as np

def vandermonde(x, N):return np.column_stack([x**(i) for i in range(N + 1)])

Compruebe que llamar esta función con x = np.arange(6) y N = 2 genera el siguiente arreglo de numpy:

[[ 1 0 0][ 1 1 1][ 1 2 4][ 1 3 9][ 1 4 16][ 1 5 25]]

Por lo tanto, el problema planteado puede resolverse planteando las ecuaciones normales (5.7):

import numpy as np

def vandermonde(x, N):return np.column_stack([x**(i) for i in range(N + 1)])

Z = vandermonde(np.arange(6), 2)Y = np.array([2.1, 7.7, 13.6, 27.2, 40.9, 61.1])A = np.linalg.solve( np.dot(Z.T, Z), np.dot(Z.T,Y) )print(A)

Utilizando numpy.vander y numpy.linalg.lstsq, el problema puede resolverse de la siguiente manera:

import numpy as np

Z = np.vander(np.arange(6), 3)Y = np.array([2.1, 7.7, 13.6, 27.2, 40.9, 61.1])A = np.linalg.lstsq(Z, Y)[0]print(A)

5.1. Regresión por mínimos cuadrados 47

Page 52: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

Interprete los resultados anteriores y grafique los datos junto con el resultado obtenido de laregresión polinomial

48 Capítulo 5. Ajuste de funciones

Page 53: Anal is is Numeric o Con Python

CAPÍTULO 6

Raíces de ecuaciones no lineales

6.1 Introducción: Raíces de ecuaciones no lineales

6.1.1 Método gráfico

Aunque el método gráfico no es el más exacto para hallar las raíces de las ecuaciones no lineales, resulta deayuda.

Ejemplo 1

Encuentre la raíz de

f(c) = 667.38

[1− exp(−0.146843c)

c

]− 40

en el intervalo de [0.5, 18.0]

import numpy as npimport matplotlib.pyplot as pltc = np.linspace(0.5, 18.0)f = 667.38*(1 - np.exp(-0.146843*c))/c - 40plt.plot(c, f)plt.grid()plt.show()

49

Page 54: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

0 2 4 6 8 10 12 14 16 1810

0

10

20

30

40

50

60

Puede notarse que la solución está entre 14 y 16. Si grafica en ese intervalo, puede notarse un poco mejor laraíz.

import numpy as npimport matplotlib.pyplot as pltc = np.linspace(14.0, 16.0)f = 667.38*(1 - np.exp(-0.146843*c))/c - 40plt.plot(c, f)plt.grid()plt.show()

50 Capítulo 6. Raíces de ecuaciones no lineales

Page 55: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

14.0 14.5 15.0 15.5 16.02.5

2.0

1.5

1.0

0.5

0.0

0.5

1.0

1.5

2.0

Se puede utilizar Scipy para encontrar las raíces de manera numérica, con mucha simplicidad. A continuaciónse muestra cómo se resuelve el problema anterior con el método de bisección, uno de los más simples paraencontrar raíces de ecuaciones no lineales.

import numpy as npfrom scipy.optimize import bisect

def f(x):return 667.38*(1 - np.exp(-0.146843*x))/x - 40

x0 = bisect(f, 0.5, 18.0)print(x0)

6.1.2 Ejercicios

1. Determine la raíz real más grande de h(x) = 2x3 − 11.7x2 + 17.7x− 5

(a) En forma gráfica.

import numpy as npimport matplotlib.pyplot as pltx = np.linspace(0.0, 4.0)h = ((2*x - 11.7)*x + 17.7)*x - 5.0plt.plot(x, h)

6.1. Introducción: Raíces de ecuaciones no lineales 51

Page 56: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

plt.grid()plt.show()

0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.06

4

2

0

2

4

6

8

import numpy as npimport matplotlib.pyplot as pltx = np.linspace(3.5, 3.6)h = ((2*x - 11.7)*x + 17.7)*x - 5.0plt.plot(x, h)plt.grid()plt.show()

52 Capítulo 6. Raíces de ecuaciones no lineales

Page 57: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

3.50 3.52 3.54 3.56 3.58 3.600.8

0.6

0.4

0.2

0.0

0.2

0.4

0.6

Puede notarse que la raíz más grande es aproximadamente 3.56.

(b) Con el método de Newton-Raphson (tres iteraciones, x0 = 3, δ = 0.001).

Este método es una aproximación a una raíz de f(x) = 0 a partir del valor inicial p0 mediante laiteración:

pk = pk−1 −f (pk−1)

f ′ (pk−1)

Un algoritmo para el método de Newton-Raphson se obtiene fácilmente al sustituir la ecuaciónanterior por la fórmula predictiva x = g(x) en el algoritmo de punto fijo. Observe, sin embargo,que el programa también debe modificarse para calcular la primera derivada.

Considerando varios problemas potenciales con el método de Newton Raphson, el programa sepodría mejorar incorporando algunas consideraciones adicionales (ver pág. 153, 154 del libroMétodos numéricos para ingenieros, de Chapra y Canale).

def newton_raphson(g, dg, p0, delta, epsilon, num_max_iteraciones):# DATOS DE ENTRADA# g es la funcion de iteración.# dg es la derivada de g# p0 es la aproximacion inicial a un cero de f# delta es la tolerancia para la diferencia entre un valor de la# iteracion y el valor de la iteracion anterior# epsilon es la tolerancia para los valores de la funcion# numMaxIteraciones es el numero maximo de iteraciones# RESULTADOS:# err es la diferencia entre dos términos consecutivos

6.1. Introducción: Raíces de ecuaciones no lineales 53

Page 58: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

# P es la sucesión {pn} completa# k es el número de iteraciones realizadas# P[k] es la aproximación al punto fijo

P = zeros(numMaxIteraciones + 1)P[0] = p0for k in range(1, numMaxIteraciones + 1):

gk = P[k - 1] - g(P[k - 1])/dg(P[k - 1])P[k] = gkerr = abs(P[k] - P[k - 1])errorRelativo = 2*err/(abs(P[k]) + delta)y = g(P[k])if (err < delta or errorRelativo < delta or abs(y) < epsilon):

breakif (k == numMaxIteraciones):

print('Se ha excedido el numero de iteraciones')return P, k, errorRelativo

def h(x):return ((2*x - 11.7)*x + 17.7)*x - 5.0

def dh(x):return (6.0*x - 23.4)*x + 17.7

P, k, error_relativo = newton_raphson(h, dh, 3.0, 0.001, 0.0001, 10)

(c) Utilizando el método newton del módulo scipy.optimize.

def h(x):return ((2*x - 11.7)*x + 17.7)*x - 5.0

def dh(x):return (6.0*x - 23.4)*x + 17.7

from scipy.optimize import newton

zero = newton(h, 3.0, dh)print(zero)

6.2 Un vistazo a la librería GNU Scientific Library (GSL)

Aprovecharemos que la librería GSL tiene rutinas para encontrar las raíces de funciones unidimensionalesarbitrarias que proporcionan acceso a los pasos intermedios de la solución, para estudiar cómo funcionan losmétodos de intervalos. La librería GSL está escrita en C.

No te preocupes si no comprendes todo el código del ejemplo siguiente (basado en el manual de referenciade la GNU GSL). Esta parte del curso es más ilustrativa y de ninguna manera exhaustiva. Lee con atenciónlos comentarios que se dan en el código, pues te servirán de mucho para comprender la intención del mismo./** =====================================================================================** Nombre del* archivo: demo_fn.h** Descripción: Definición de

54 Capítulo 6. Raíces de ecuaciones no lineales

Page 59: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

* + Estructura parametros_cuadratica. Esta estructura almacena* los coeficientes {a, b, c} de un polinomio cuadrático* ax^2 + bx + c como números de tipo double.* Declaración de prototipos de funciones para* + Evaluar un polinomio cuadrático, dado por los parámetros* apuntados por params, en un valor x (cuadratica)* + Evaluación de la derivada del polinomio cuadrático* (deriv_cuadratica)* + Evaluación simultánea del polinomio y de su derivada* (fdf_cuadratica)** =====================================================================================*/

struct parametros_cuadratica{

double a, b, c;};

double cuadratica(double x, void *params);

double deriv_cuadratica(double x, void *params);

void fdf_cuadratica(double x,void *params,double *y,double *dy);

A continuación se muestra la implementación de los prototipos declarados en demo_fn.h/** =====================================================================================** Nombre del* archivo: demo_fn.c** Descripción: Definición (implementación) de los prototipos en demo_fn.h** =====================================================================================*/#include "demo_fn.h"

double cuadratica(double x, void *params){

struct parametros_cuadratica *p = (struct parametros_cuadratica *) params;double a = p->a;double b = p->b;double c = p->c;return (a * x + b) * x + c;

}

double deriv_cuadratica(double x, void *params){

struct parametros_cuadratica *p = (struct parametros_cuadratica *) params;double a = p->a;double b = p->b;double c = p->c;return 2.0 * a * x + b;

}

6.2. Un vistazo a la librería GNU Scientific Library (GSL) 55

Page 60: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

void fdf_cuadratica(double x,void *params,double *y,double *dy)

{struct parametros_cuadratica *p = (struct parametros_cuadratica *) params;double a = p->a;double b = p->b;double c = p->c;*y = (a * x + b) * x + c;*dy = 2.0 * a * x + b;

}

Finalmente, el siguiente programa utiliza los dos archivos de código fuente anteriores para encontrar la raízdel polinomio cuadrático x2 − 5 = 0:/** =====================================================================================** Nombre del* archivo: demo_root.c** Descripción: Ejemplo del uso de rutinas de GSL para encontrar las raíces* de funciones unidimensionales arbitrarias.* Compilar con: icc demo_root.c -lgsl -o demo_root* =====================================================================================*/

#include <stdio.h>#include <gsl/gsl_errno.h>#include <gsl/gsl_math.h>#include <gsl/gsl_roots.h>

#include "demo_fn.c"

int main (){

int estado; /* Indica el estado de una iteración del método */int iter = 0; /* Contador de iteraciones */const int MAX_ITER = 100; /* Número máximo de iteraciones */const gsl_root_fsolver_type *T; /* Apuntador al _tipo_ de solucionador */gsl_root_fsolver *s; /* Apuntador a la instancia del solucionador */double r = 0.0; /* Valor inicial de la raíz */double raiz_esperada = sqrt (5.0);/* Valores iniciales de los limites del intervalo de búsqueda */double x_inferior = 0.0, x_superior = 5.0;

/** Estructura capaz de apuntar a* + la función cuya raíz desea encontrarse* + los parámetros que necesita la función*/gsl_function F;struct parametros_cuadratica params = {1.0, 0.0, -5.0};F.function = &cuadratica;F.params = &params;

/* Se utiliza el método de bisección.

56 Capítulo 6. Raíces de ecuaciones no lineales

Page 61: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

* NOTA: Se pueden seleccionar entre diferentes tipos de solucionadores.* Verifique el manual de la GSL*/T = gsl_root_fsolver_bisection;s = gsl_root_fsolver_alloc (T); /* Se crea la nueva instancia del solucionador */

/** Se inicializa el solucionador s para que use la función F y* el intervalo inicial de búsqueda [x_inferior, x_superior]*/gsl_root_fsolver_set (s, &F, x_inferior, x_superior);/* Imprimir el nombre del método usado */printf ("Usando el método %s\n", gsl_root_fsolver_name (s));/* Imprimir el encabezado de resultados intermedios */printf ("%5s [%9s, %9s] %9s %10s %9s\n",

"iter", "inferior", "superior", "raiz", "err", "err(est)");

/** Iterar mientras que* el estado sea GSL_CONTINUE y* no se haya alcanzado el número máximo de iteraciones*/do {

iter++; /* Incrementar en uno el contador de iteraciones *//** Lleva a cabo una iteración del solucionador s.* Si la iteración encuentra un error inesperado, la variable estado* contiene un código de error*/estado = gsl_root_fsolver_iterate (s);/* Actualiza la mejor estimación de la raíz que se tiene al momento */r = gsl_root_fsolver_root (s);/* Actualiza los límites del mejor intervalo que encierra una posible raíz */x_inferior = gsl_root_fsolver_x_lower (s);x_superior = gsl_root_fsolver_x_upper (s);/** Verificar la convergencia del método en el intervalo con* error absoluto = 0.0* error relativo = 0.001* El test devuelve GSL_SUCCESS si el método ha convergido*/estado = gsl_root_test_interval (x_inferior, x_superior, 0, 0.001);if (estado == GSL_SUCCESS)

printf ("El método converge:\n");/* Mostrar información sobre la iteración actual */printf ("%5d [%.7f, %.7f] %.7f %+.7f %.7f\n",

iter,x_inferior,x_superior,r,r - raiz_esperada,x_superior - x_inferior);

}while (estado == GSL_CONTINUE && iter < MAX_ITER);

/* Liberar la memoria asociada al solucionador s */gsl_root_fsolver_free (s);

6.2. Un vistazo a la librería GNU Scientific Library (GSL) 57

Page 62: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

/* Terminar el programa devolviendo el valor de la variable estado */return estado;

} /* ---------- Fin de la función main ---------- */

El resultado de ejecutar el programa anterior es:

Usando el método bisectioniter [ inferior, superior] raiz err err(est)

1 [0.0000000, 2.5000000] 1.2500000 -0.9860680 2.50000002 [1.2500000, 2.5000000] 1.8750000 -0.3610680 1.25000003 [1.8750000, 2.5000000] 2.1875000 -0.0485680 0.62500004 [2.1875000, 2.5000000] 2.3437500 +0.1076820 0.31250005 [2.1875000, 2.3437500] 2.2656250 +0.0295570 0.15625006 [2.1875000, 2.2656250] 2.2265625 -0.0095055 0.07812507 [2.2265625, 2.2656250] 2.2460938 +0.0100258 0.03906258 [2.2265625, 2.2460938] 2.2363281 +0.0002601 0.01953129 [2.2265625, 2.2363281] 2.2314453 -0.0046227 0.009765610 [2.2314453, 2.2363281] 2.2338867 -0.0021813 0.004882811 [2.2338867, 2.2363281] 2.2351074 -0.0009606 0.0024414

El método converge:12 [2.2351074, 2.2363281] 2.2357178 -0.0003502 0.0012207

Verifica manualmente los resultados de la tabla anterior.

58 Capítulo 6. Raíces de ecuaciones no lineales

Page 63: Anal is is Numeric o Con Python

CAPÍTULO 7

Diferenciación e integración numérica

7.1 Diferenciación numérica básica

• Aproximación a la primera derivada con diferencia hacia adelante

f ′(xi) =f(xi+1)− f(xi)

xi+1 − xi+O(xi+1 − xi)

• Aproximación a la primera derivada con diferencia hacia atrás

f ′(xi) =f(xi)− f(xi−1)

xi − xi−1+O(xi − xi−1)

• Aproximación a la primera derivada con diferencias centradas

f ′(xi) =f(xi+1)− f(xi−1)

2(xi+1 − xi−1)+O

(h2)

El siguiente bloque de código resuelve el problema:

def derivadasConDifDivididas(f, xi, h):difHaciaAdelante = (f(xi + h) - f(xi))/hprint("Con diferencia hacia adelante: {}".format(difHaciaAdelante))difHaciaAtras = (f(xi) - f(xi - h))/hprint("Con diferencia hacia atras: {}".format(difHaciaAtras))difCentradas = (f(xi + h) - f(xi - h))/(2*h)print("Con diferencia centrada: {}".format(difCentradas))

def f(x):return (((-0.1*x - 0.15)*x - 0.5)*x - 0.25)*x + 1.2

derivadasConDifDivididas(f, 0.5, 0.5)derivadasConDifDivididas(f, 0.5, 0.25)

59

Page 64: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

Utilizando Scipy:

from scipy.misc import derivative

def f(x):return (((-0.1*x - 0.15)*x - 0.5)*x - 0.25)*x + 1.2

df = derivative(f, 0.5, 0.25)

7.2 Integración numérica

Algunas funciones pueden ser integradas de manera analítica, mientras que muchas otras no, y entoncesse debe recurrir a una aproximación numérica a la integral. Por ejemplo, en el campo de la termodinámicaestadística, el modelo de Debye para calcular la capacidad calórica de un sólido considera la siguiente función

Φ(x) =

∫ x

0

t3

et − 1dt

Puesto que ho hay una expresión analítica para Φ(x), debemos usar algún método de integración numéricapara calcular sus valores.

7.2.1 Ejemplo 1

Calcule∫ 4

0

x2 dx utilizando scipy.integrate y compare con el resultado analítico:

from scipy import integratex2 = lambda x: x**2integ = integrate.quad(x2, 0.0, 4.0)print integ

Ahora calcule de manera numérica:

1. Φ(5)

2.∫ ∞

0

e−x dx. Pista: utilice inf para denotar +∞.

La regla trapezoidal

La regla trapezoidal es la más sencilla de todas las fórmulas de integración cerrada de Newton-Cotes. Geo-métricamente, la regla trapezoidal es equivalente a aproximar el área bajo la curva con la del trapecio bajola línea recta que conecta f(a) y f(b) en la Figura Regla trapezoidal.

Recuerde que la fórmula para calcular el área de un trapecio es la altura por el promedio de las bases. Ennuestro caso, el concepto es el mismo, pero el trapecio está sobre su lado.

La regla compuesta del trapecio

Un método intuitivo para hallar el área limitada por una curva y = f(x) en un intervalo [a, b] es dar unaaproximación a dicha área sumando las áreas de una serie de trapecios construidos sobre los intervalos{[xk, xk+1]} de una partición de [a, b].

60 Capítulo 7. Diferenciación e integración numérica

Page 65: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

Figura 7.1: Regla trapezoidal

from pylab import *from matplotlib.patches import Polygon

def func(x):return (x-3) * (x-5) * (x-7) + 85

ax = subplot(111)

a, b = 2, 9 # Area de la integralx = arange(0, 10, 0.01)y = func(x)plot(x, y, linewidth=1)# make the shaded regionix = linspace(a, b, 4)iy = func(ix)verts = [(a,0)] + zip(ix,iy) + [(b,0)]poly = Polygon(verts, facecolor='0.8', edgecolor='k')ax.add_patch(poly)

markerline, stemlines, baseline = stem(ix, iy, 'k-.')setp(markerline, 'markerfacecolor', 'b')

axis([0,10, 0, 180])figtext(0.9, 0.05, 'x')figtext(0.1, 0.9, 'y')ax.set_xticks((a,b))ax.set_xticklabels(('a','b'))

7.2. Integración numérica 61

Page 66: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

ax.set_yticks([])show()

Supongamos que se divide el intervalo [a, b] en M subintervalos [xk, xk+1] de anchura común h = (b− a)/Mmediante una partición cuyos nodos xk = a + kh, para k = 0, 1, . . . ,M , están equiespaciados. La reglacompuesta del trapecio con M subintervalos se puede expresar de las siguientes formas equivalentes:

T (f, h) =h

2

M∑k=1

(f(xk−1) + f(xk)) (7.1)

o bien

T (f, h) =h

2(f0 + 2f1 + 2f2 + 2f3 + · · ·+ 2fM−2 + 2fM−1 + fM ) (7.2)

o bien

T (f, h) =h

2(f(a)− f(b)) + h

M−1∑k=1

f(xk) (7.3)

Este valor es una aproximación a la integral de f(x) en [a, b], lo que se escribe como∫ b

a

f(x) dx ≈ T (f, h)

7.2.2 Ejemplo 2

Consideremos f(x) = 2+ sin(2√x). Vamos a usar la regla compuesta del trapecio con 11 nodos para calcular

una aproximación a la integral de f(x) en el intervalo [1, 6].

Para los once nodos, tomamos M = 10, con lo que h = (6−1)/10 = 1/2. Usando la fórmula (7.3), los cálculosson:

T

(f,

1

2

)=

1/2

2(f(1) + f(6)) +

1

2

(f

(3

2

)+ f(2) + f

(5

2

)+ f(3) + f

(7

2

)+ f(4) + f

(9

2

)+ f(5) + f

(11

2

))=

1

4(2.9093 + 1.01735) +

1

2(2.63815 + 2.30807 + 1.97931 + 1.68305 + 1.43530 + 1.24319 + 1.10831 + 1.02872 + 1.00024)

=1

4(3.92665) +

1

2(14.42438)

= 0.98166 + 7.21219

= 8.19385

Compruebe el resultado anterior manualmente y después utilizando el siguiente código:

62 Capítulo 7. Diferenciación e integración numérica

Page 67: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

from numpy import linspace, sin, sqrtfrom scipy.integrate import trapz

x = linspace(1, 6, 11)y = 2 + sin( 2*sqrt(x) )T = trapz(y, x)print(T)

7.2. Integración numérica 63

Page 68: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

64 Capítulo 7. Diferenciación e integración numérica

Page 69: Anal is is Numeric o Con Python

CAPÍTULO 8

Ecuaciones Diferenciales Ordinarias

8.1 Ecuaciones Diferenciales Ordinarias

Considere la ecuación:

dy

dt= 1− e−t

Esta ecuación es separable, por lo que puede resolverse directamente mediante integración:

y(t) = t+ e−t + C

donde C es la constante de integración. En esta solución existe un grado de libertad, dado por la elección dela constante de integración C.

import matplotlib.pyplot as pltimport numpy as npnum_puntos = 81t = np.linspace(-2.0, 5.0, num_puntos)num_curvas = 5y = np.zeros((num_curvas, num_puntos))for i, C in enumerate(range(-2, num_curvas - 2)):

y[i] = t + np.exp(-t) + Cplt.plot(t, y[i])

plt.grid()plt.show()

65

Page 70: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

2 1 0 1 2 3 4 51

0

1

2

3

4

5

6

7

8

A diferencia de la ecuación diferencial dada, no todas pueden resolverse de manera exacta (ya sea medianteintegración directa o por alguno de los métodos “tradicionales”). A menudo se da el caso de que no hayuna soluciñon analítica conocida, por lo que necesitamos aproximaciones numéricas. A modo de ejemplo,consideremos, en el contexto de la dinámica de poblaciones, un sistema no lineal que es una modificación delas ecuaciones de Lotka-Volterra

x = f(t, x, y) = x− xy − 1

10x2

y = g(t, x, y) = xy − y − 1

20y2

para 0 ≤ t ≤ 30 con la condición inicial x(0) = 2 e y(0) = 1. La solución numérica se consigue con el siguientecódigo:

import matplotlib.pyplot as pltimport numpy as npfrom scipy.integrate import odeint

x0 = [2, 1]

def f(xVec, t):x, y = xVecf0 = x - x*y - x**2 / 10.0f1 = x*y - y - y**2 / 20.0return [f0, f1]

66 Capítulo 8. Ecuaciones Diferenciales Ordinarias

Page 71: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

t = np.linspace(0.0, 30.0, 3001)xVec = odeint(f, x0, t)x = xVec[:, 0]y = xVec[:, 1]plt.plot(x, y)plt.show()

8.1.1 Mezclas de soluciones salinas

La mezcla de dos soluciones salinas de distintas concentraciones da lugar a una ecuación diferencial de primerorden, que define la cantidad de sal que contiene la mezcla.

Supongamos que un tanque está parcialmente lleno con 100 galones de salmuera (sal disuelta en agua), con10 lb de sal disuelta. Le entra salmuera con 1

2lb de sal por galón a razón de 6 gal/min. El contenido del

tanque está bien mezclado y de él sale a razón de 6 gal/min. El contenido del tanque está bien mezclado yde él sale a razón de 4 gal/min de solución. Calcule la cantidad de libras de sal que hay en el tanque a los30 minutos.

Ri =

(1

2

lbgal

)(6

galmin

)= 3

lbmin

Ro =

(A

100 + 2t

lbgal

)(4

galmin

)=

2A

50 + t

lbmin

dA

dt= Ri −Ro = 3− 2A

50 + t

La ecuación diferencial anterior se puede expresar en la forma estándar para las ecuaciones lineales:dA

dt+

2

50 + tA = 3 (8.1)

El factor integrante es:

e∫

250+t dt = e2 ln(50+t) = (50 + t)2 (8.2)

Multiplicando la Ec. (8.1) por el factor integrante (8.2)

(50 + t)2(dA

dt+

2

50 + tA

)= 3(50 + t)2

identificamos el lado izquierdo como d

dt

[(50 + t)2A

], por lo que tenemos la expresión más simple:

d

dt

[(50 + t)2A

]= 3(50 + t)2

que hay que resolver por integración de ambos miembros:

(50 + t)2A = 3

∫(50 + t)2 dt = (50 + t)3 + C

Sustituyendo la condición inicial A(0) = 10, en la expresión anterior, obtenemos C = −100000. La soluciónde la Ec. (8.1) es:

A(t) = 50 + t− 100000

(50 + t)2

8.1. Ecuaciones Diferenciales Ordinarias 67

Page 72: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

Por lo tanto, a los 30 min., la cantidad de sal disuelta en el tanque es A(30) = 64.375 lb. Resuelva demanera numérica el problema. Grafique la solución exacta junto con la solución numérica,hasta los 35 min.

8.1.2 Un resorte de Hooke con estímulo senoidal

El movimiento vertical de un peso sujeto a un resorte que obedece la Ley de Hooke, y que tiene un estímulosenoidal externo se puede modelar con la ecuación diferencial:

y + 2cy + ω20y = F0 sin(ωt) (8.3)

donde c, ω0 y ω son números reales positivos. Considéremos el caso en que c < ω0, que corresponde a unsistema sub-amortiguado. Además suponga que ω < ω0. Con estas suposiciones, la solución general de (8.3)se puede expresar como y = yu + yd, donde

yu = C1e−ct cos

(t√ω20 − c2

)+ C2e

−ct sin(t√ω20 − c2

)(8.4)

yd = F0M(ω) sin[ωt+ ϕ(ω)] (8.5)

C1, C2 dependen de las condiciones iniciales y

M(ω) =1√

(ω20 − ω2)2 + 4c2ω2

(8.6)

ϕ(ω) = arctan(

−2cω

ω20 − ω2

)− π < ϕ(ω) < 0 (8.7)

Ejemplo

El sistema

y + y + 4y = 12 sin t

con c = 1/2, ω0 = 2, ω = 1, sujeto a las condiciones iniciales y(0) = 0, y(0) = 0 tiene la solución

y(t) = e−t/2

[6

5cos(√

15

2t

)− 2

5

√15 sin

(√15

2t

)]+

6

5

√10 sin(t− 0.32175)

import matplotlib.pyplot as pltimport numpy as nptfinal = 20.0num_puntos = tfinal * 100 + 1t = np.linspace(0.0, tfinal, num_puntos)theta = np.sqrt(15)*t/2.0yu = np.exp(-0.5*t)*(1.2*np.cos(theta) - 1.54919*np.sin(theta))yd = 1.2*np.sqrt(10)*np.sin(t - 0.32175)y = yu + ydplt.plot(t, y)plt.grid()plt.show()

68 Capítulo 8. Ecuaciones Diferenciales Ordinarias

Page 73: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

0 5 10 15 204

3

2

1

0

1

2

3

4

Una solución numérica de este problema, utilizando un método de Runge-Kutta de orden (4)5 debido aDormand y Prince (con control del tamaño de paso y salida densa) está dada por el siguiente código:

import matplotlib.pyplot as pltimport numpy as npfrom scipy.integrate import odefrom math import sin

y0 = [0, 0]t0 = 0

def f(t, y, c, omega0, F0, omega):x, v = yxDot = vvDot = -omega0*omega0 *x - 2*c*v + F0*sin(omega*t)return [xDot, vDot]

r = ode(f).set_integrator('dopri5')

r.set_initial_value(y0, t0)#(c = 0.5, omega0 = 2.0, F0 = 12.0, omega = 1.0)r.set_f_params(0.5, 2.0, 12.0, 1.0)

t1 = 20.0t = np.linspace(0.0, t1, t1*100 + 1)

8.1. Ecuaciones Diferenciales Ordinarias 69

Page 74: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

dt = t[1]y = np.zeros(len(t))y[0] = y0[0]

i = 1while r.successful() and r.t <= t1:

r.integrate(r.t + dt)t[i] = r.ty[i] = r.y[0].reali += 1

plt.plot(t, y)plt.grid()plt.axis([0.0, 20.0, -4.0, 4.0])plt.show()

8.2 PROYECTO FINAL: Rescatando a la tripulación del Apollo 13

En 1970, la tripulación del Apollo 13 abortó el aterrizaje lunar debido a una explosión en uno de los tanquesde oxígeno. Utilizando los siguientes datos, simule la trayectoria de la nave

Descripción ValorMasa de la Tierra 5.97× 1024 kg

Radio terrestre (en el ecuador) 6.378× 106 m

Constante de Gravitación Universal 6.67× 10−11 m3/(kg · s2)Masa de la Luna 7.35× 1022 kg

Radio de la Luna 1.74× 106 kg

Distancia Tierra a Luna (en realidad no es cte.) 400.5× 106 mPeriodo de la Luna 27.3 díasÁngulo inicial de la Luna −61◦

Duración total del viaje 12 díasPosición inicial de la nave (en t = 0) [−6.701× 106, 0]T m

Velocidad inicial de la nave (en t = 0) [0,−10.818× 103]T m/s

Simule

• Una reducción (instantánea) en la rapidez de 7.04 m/s a los 101,104 segundos

• Un incremento (instantáneo) de la velocidad, dado por la variable boost (en m/s), a los 212,100 segun-dos. Pruebe con los valores siguientes valores para boost: −10.0, 10.0, 50.0, 100.0.

Suponga que la Tierra está en el centro del plano coordenado. Considere el movimiento de traslación de laLuna alrededor de la Tierra, como una órbita circular.

Utilizando la Ley de Gravitación Universal, y la segunda Ley de Newton, obtenemos una ecuación diferencialde segundo orden, explícita y no lineal, que determina la aceleración de la nave

xn = −GmT

∥xn∥3xn +G

mL

∥ xL − xn ∥3 (xL − xn) (8.8)

donde xn es la posición de la nave (relativa a la Tierra); mT , la masa de la Tierra; G, la constante deGravitación Universal; mL, la masa de la Luna; xL es la posición de la Luna.

Una gráfica de la ruta seguida por la nave debe verse similar a la siguiente:

70 Capítulo 8. Ecuaciones Diferenciales Ordinarias

Page 75: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

8.2. PROYECTO FINAL: Rescatando a la tripulación del Apollo 13 71

Page 76: Anal is is Numeric o Con Python

Programacion con Python, Release 0.4

72 Capítulo 8. Ecuaciones Diferenciales Ordinarias

Page 77: Anal is is Numeric o Con Python

CAPÍTULO 9

Índices y tablas

• genindex

• modindex

• search

73