Академический Документы
Профессиональный Документы
Культура Документы
Release 0.4
02 de September de 2013
ndice general
1 Programacin bsica 1.1 Introduccin . . . . . . . . 1.2 Python bsico . . . . . . . 1.3 Expresiones y operadores . 1.4 Procedimientos y funciones 1.5 Estructuras de control . . . 2 Grcas 2.1 Grcas simples . . . . . . 2.2 Grcas de contorno . . . . 2.3 Grcas en 3D . . . . . . . 2.4 Ejercicios . . . . . . . . . . 2.5 Grcas de algunos campos
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
3 3 8 9 10 11 23 23 27 28 29 30
. . . . . . . . . . . . . . . . . . . . simples
3 lgebra lineal 33 3.1 Arreglos de NumPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 3.2 lgebra Lineal bsica con NumPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.3 Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 4 Polinomios e interpolacin 39 4.1 Introduccin a la Interpolacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 4.2 Interpolacin segmentaria (splines) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 5 Ajuste de funciones 43 5.1 Regresin por mnimos cuadrados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 6 Races de ecuaciones no lineales 49 6.1 Introduccin: Races de ecuaciones no lineales . . . . . . . . . . . . . . . . . . . . . . . . . . 49 6.2 Un vistazo a la librera GNU Scientic Library (GSL) . . . . . . . . . . . . . . . . . . . . . . 54 7 Diferenciacin e integracin numrica 59 7.1 Diferenciacin numrica bsica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 7.2 Integracin numrica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
8 Ecuaciones Diferenciales Ordinarias 65 8.1 Ecuaciones Diferenciales Ordinarias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 8.2 PROYECTO FINAL: Rescatando a la tripulacin del Apollo 13 . . . . . . . . . . . . . . . . 70 9 ndices y tablas 73
ndice
73
ii
Contents:
ndice general
ndice general
CAPTULO
Programacin bsica
1.1 Introduccin
1.1.1 Por qu aprender a programar?
Porque es una habilidad que aumenta tus posibilidades de adquirir un mejor empleo. Para realizar clculos intensos, es necesario utilizar una computadora, pues hacerlos a mano sera muy tardado o imposible. Ejemplos de reas en las que puedes aplicar la programacin: Mtodos numricos: Resuelva de manera numrica (utilizando el mtodo de Euler) el sistema masa-resorte dado por la ecuacin diferencial mu + u + ku = F (t), u(0) = U0 , u (0) = 0
Sistema masa resorte que se describe mediante una ecuacin diferencial Gracacin. A continuacin se muestra un histograma obtenido a partir de una distribucin de probabilidad normal.
import matplotlib.pyplot as plt import numpy as np x = np.random.randn(1000) plt.hist(x, 20) plt.grid() plt.show()
1.1.4 Temario
1. Programacin con software matemtico. (a) Conceptos bsicos de programacin (con Python 3.x). Ejemplo: funciones. (b) Lectura y escritura de datos simple. 2. Grcas con software matemtico. (a) Matplotlib y Numpy. (b) Grcas simples en 2D y en 3D.
import matplotlib.pyplot as plt import numpy as np x = 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 - 1 cs = plt.contour(ellipses) plt.clabel(cs) plt.show()
0.000
0.200
-0.400
-0.800
-0.600
-0.200
50
0.000 100 150
-0.400
200
250
Grca de contornos. 3. lgebra lineal. (a) Matrices y vectores. (b) Sistemas de ecuaciones lineales.
1.1. Introduccin
Programacion con Python, Release 0.4 [ Para resolver el sistema de ecuaciones lineales Ax = b dado por A =
import numpy as np A = np.array([[3.0, 2.0], [-1.0, 2.0]]) b = np.array([18.0, 2.0]) from numpy.linalg import solve x = solve(A, b) print(x) # Solucin: x = [4.0, 3.0]
] [ ] 3 2 18 yb= : 1 2 2
4. Polinomios e interpolacin.
import numpy as np from scipy.interpolate import interp1d import matplotlib.pyplot as plt x = 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) Regresin. (b) Interpolacin. 6. Races de ecuaciones no lineales. Se tratar de hallar las races de ecuaciones. Es decir, el problema es: resolver f (x) = 0 para x. Ejemplo: determine la raz ms grande de h(x) = 2x3 11.7x2 + 17.7x 5 en forma grca.
import numpy as np import matplotlib.pyplot as plt x = np.linspace(0, 4) y = 2 * x**3 - 11.7 * x**2 + 17.7 * x - 5 plt.plot(x, y) plt.grid() plt.show()
7. Funciones de splines e interpolacin no lineal. 8. Diferenciacin e integracin numrica. 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 un estmulo senoidal externo se puede modelar con la ecuacin diferencial:
2 y + 2cy + 0 y = F0 sin(t)
(1.1)
donde c, 0 y son nmeros reales positivos. Considremos el caso en que c < 0 , que corresponde a un sistema sub-amortiguado. Adems suponga que < 0 . Con estas suposiciones, la solucin general de (1.1) se puede expresar como y = yu + yd , donde ( ) ( ) 2 c2 + C ect sin t 2 c2 yu = C1 ect cos t 0 (1.2) 2 0 yd = F0 M ( ) sin[t + ( )] C1 , C2 dependen de las condiciones iniciales y M ( ) = 1 (1.4) (1.5) (1.3)
1.1. Introduccin
1.2.1 Prctica 1
1. Descarga WinPython de http://code.google.com/p/winpython/downloads/list y ejecuta el instalador (Verica primero si tienes una computadora con un sistema operativo de 64 bits o de 32 bits y descarga la versin ms apropiada para ti. Si tienes dudas, pregunta a tu profesor cmo averiguar esto. Otra opcin que tienes es descargar la versin de 32 bits, que puede ejecutarse en los dos tipos de computadoras). 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 seccin a la vez que vas leyendo el tutorial. Anota las dudas que tengas para que puedas preguntar ms adelante a tu profesor.
1.2.2 Prctica 2
Visita la pgina http://sta.not.iac.es/~rcardenes/hg/diveintopython3-es/native-datatypes.html y estudia los tipos de datos nativos que soporta Python 3 (puedes consultar la versin original en ingls en http://getpython3.com/diveintopython3/native-datatypes.html)
Con ayuda del siguiente bloque de cdigo, verica la posicin de la pelota a los 0.6 segundos de ser lanzada, 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 velocity g = 9.81 # acceleration of gravity t = 0.6 #time y = v0*t - 0.5*g*t**2 # vertical position print(y)
Cules son los operadores que utilizas para la multiplicacin y para la exponenciacin? 2. Considere el movimiento vertical de la pelota dado por la ecuacin (1.6). Cunto tiempo le toma a la pelota alcanzar la altura yc ? 1 2 gt v0 t + yc = 0 2 Usando la frmula general para encontrar las races de una ecuacin de segundo grado, comprueba que las soluciones son: Comprueba que las soluciones estn dadas por las races de la ecuacin ( t1 = v0
2 v0
) 2gyc /g,
( ) 2 t2 = v0 + v0 2gyc /g
(1.7)
Utilizando el siguiente bloque de cdigo, averigua cules son los dos instantes de tiempo en que una pelota est a una altura de 0.3 m, si la velocidad inicial de la pelota es de 6 m/s:
v0 = 5 g = 9.81 yc = 0.2 import math t1 = (v0 - math.sqrt(v0**2 - 2*g*yc))/g t2 = (v0 + math.sqrt(v0**2 - 2*g*yc))/g print('En t={0:.4f} s y t={1:.4f} s, la altura es {2:.4f} m.'.format(t1, t2, yc))
Utilizando el siguiente bloque de cdigo, indica cules son los valores que toma la variable v:
import math as m # m is now the name of the math module v = m.sin(m.pi) from math import log as ln v = ln(5) from math import sin as s, cos as c, log as ln v = s(x)*c(x) + ln(x)
4. Con ayuda del siguiente cdigo, calcula las dos races complejas de la ecuacin cuadrtica 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)
2. Llama la funcin anterior con los argumentos 3 Hola Cul es el tipo de estos argumentos? Utiliza la funcin type() 3. Convierte de metros a unidades de longitud inglesas. Construye un programa que reciba una longitud en 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 vericacin puede usar los siguientes datos: 640 m = 25196.85 pulgadas = 2099.74 pies = 699.91 yardas = 0.3977 millas inglesas 4. Modica (en caso de ser necesario) el programa del ejercicio anterior de modo que utilices funciones para resolver el problema propuesto. 5. Basndote en el siguiente cdigo, calcula el rea de un paralelogramo, de un cuadrado y de un crculo, as como el volumen de un cono utilizando funciones:
10
from math import pi h = 5.0 # altura b = 2.0 # base r = 1.5 # radio area_paralelogramo = h*b print("El area del paralelogramo es {0:.3f}".format(area_paralelogramo)) area_cuadrado = b**2 print("El area del cuadrado es {}".format(area_cuadrado)) area_circulo = pi*r**2 print("El area del circulo es {0:.3f}".format(area_circulo)) volumen_cono = 1.0/3*pi*r**2*h print("El volumen del cono es {0:.3f}".format(volumen_cono))
11
Ejemplo 2 Construya un diagrama de ujo (vea la Figura Seleccin doble (if else).) tal que dado como dato la calicacin de un alumno en un examen, escriba aprobado si su calicacin es mayor o igual a 70 y reprobado en caso contrario.
else).
Ejemplo 3 Construya un diagrama de ujo tal que dado como datos la categora y el sueldo de un trabajador, calcule el aumento correspondiente teniendo en cuenta la siguiente tabla. Imprima la categora del trabajador y su nuevo sueldo. Categora 1 2 3 4 Aumento 15% 10% 8% 7%
12
cat = 2 sue = 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 categora del trabajador es {}".format(cat)) print("El nuevo sueldo es {}".format(n_sue))
Cul es el salario del trabajador (considerando que el salario actual es de $1000.00) para cada categora? Ejercicios 1. Construya un diagrama de ujo tal que dado como dato un nmero entero, determine e imprima si el mismo es positivo, negativo o cero. Utilice la estructura de seleccin multiple. Despus codique su solucin en Python. 2. En una tienda efectan un descuento a los clientes dependiendo del monto de la compra. El descuento se efecta 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 ujo que ilustre la solucin del ejercicio. Despus codique su solucin en Python. 3. En un estudio se ha hecho un estudio sobre los pacientes registrados durante los ltimos 10 aos, con el objeto de hacer una aproximacin de los costos de internacin por paciente. Se obtuvo un promedio diario segn el tipo de enfermedad que aqueja al paciente. Adems se pudo determinar que en promedio todos los pacientes con edad entre 14 y 22 aos implican un costo adicional del 10%. La siguiente tabla expresa los costos diarios, segn el tipo de enfermedad. Tipo de enfermedad 1 2 3 4 Costo/paciente/da 25 16 20 32
Construya un programa en Python que calcule e imprima el costo total que representa un paciente (pista: considere el nmero de das que el paciente permanece internado).
13
Ejemplo 1 Imprima una tabla de conversin de grados Celsius a grados Fahrenheit. Dicha tabla debe verse como la siguiente: Celsius -20 -15 -10 -5 0 5 10 15 20 25 30 35 40 Fahrenheit -4.0 5.0 14.0 23.0 32.0 41.0 50.0 59.0 68.0 77.0 86.0 95.0 104.0
List Comprehension. Dado que recorrer una lista elemento a elemento y por cada uno de ellos crear otro nuevo 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 expresin que envuelve al elemento e. A continuacin ponemos varios ejemplos:
for:
Una versin ms pythonica del ciclo anterior se consigue utilizando una list comprehension:
14
Ejemplo 2 Las sumatorias ocurren con frecuencia en las matemticas. Por ejemplo, la funcin sin(x) puede calcularse como un polinomio: sin(x) x x3 x5 x7 + + 3! 5! 7! (1.8)
donde 3! = 3 2 1, 5! = 5 4 3 2 1, etc. son factoriales. La expresin k ! puede calcularse con math.factorial(k). Se requiere de un nmero innito de trminos en el lado derecho de (1.8) para que sea vlido usar el signo de igualdad. Con un nmero nito de trminos, se obtiene una aproximacin de la funcin sin(x). Suponga que es necesario calcular el lado derecho de (1.8) para potencias de hasta suma anterior con un ciclo while de Python, utiliza lo siguiente: 1. Un contador
k N = 25.
El clculo de la
que toma los valores impares desde 1 hasta un algn nmero mximo N.
sumatoria,
El propsito de cada iteracin del ciclo es calcular un nuevo trmino y aadirlo a sumatoria. Dado que el signo de cada trmino se alterna, podemos introducir una variable signo que cambie entre 1 y 1 en cada iteracin del ciclo. Las ideas anteriores pueden codicarse en Python de la siguiente manera:
x = 1.2 # asignar algn valor N = 25 # maxima potencia en la suma k = 1 sumatoria = x signo = 1.0 import math while k < N: signo = - signo k = k + 2 term = signo * x**k / math.factorial(k) sumatoria = sumatoria + term print("sin({0:g}) = {1:g} (aproximacin 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 funcin denida en un intervalo (a, a + T ), donde a R y T > 0 es el periodo de la funcin. f (t) puede escribirse como ( ) ( )] [ a0 2nt 2nt f (t) = + an cos + bn sin 2 T T n=1
15
2 bn = T
( f (t) sin
2nt T 2nt T
) dt ) dt
El uso ms frecuente de la serie de Fourier es para representar funciones peridicas. Lo que se hace es denir la funcin para un intervalo (a, a + T ) con una serie de Fourier. El resultado es una funcin denida en todo el eje real. a0 siempre da el valor promedio de la funcin. El valor que da la serie geomtrica de Fourier para El valor 2 los valores en que la funcin presenta discontinuidades es el valor promedio de la funcin. Un desarrollo en serie de Fourier para f (t) denida de acuerdo con la gura
import matplotlib.pyplot as plt import numpy as np x1 = 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
3 2 1 0 1 2 0.0
0.5
1.0
1.5
2.0
est dado por las siguientes expresiones: a0 = 1 an = 0 3 n bn = [1 (1) ] n T =2 es decir, la solucin es: f (t) = 1 3 n + [1 (1) ] sin(nt) 2 n=1 n
La grca siguiente se obtiene utilizando los primeros 3 trminos de la sumatoria de la ltima expresin para f (t):
import matplotlib.pyplot as plt import numpy as np from numpy import pi
17
num_puntos = 301 t = np.linspace(-2.0, 4.0, num_puntos) f = np.zeros((3, num_puntos)) for n in range(3): impar = 2*n + 1 theta = impar*pi*t f[n] = np.sin(theta)/impar plt.plot(t, f[n]) y = 0.5 + 6.0/pi*f.sum(0) plt.plot(t, y) plt.grid() plt.show()
Modique el programa anterior para visualizar la seal peridica que se obtiene al sumar los primeros diez trminos de la serie. Despus visualize la seal correspondiente a 100 trminos. Ejercicios 1. Escriba un programa que genere todos los nmeros impares desde 1 hasta n. Fije un valor para n al inicio del programa y use un ciclo while para calcular los nmeros. Asegrese de que si n es un nmero par, el nmero impar ms grande generado es n - 1. Nombre del programa: impar.py 2. Modique el programa del ejercicio 1 y almacene los nmeros impares generados en una lista. Empiece con una lista vaca y use un ciclo while donde en cada iteracin del ciclo agregue un nuevo elemento a la 18 Captulo 1. Programacin bsica
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 lista_impares2.py
for
range).
k=1
Este programa no funciona correctamente. Cules son los tres errores? Si usted intenta ejecutar el programa, nada suceder en la pantalla. Teclee Ctrl-C, es decir, presione (y deje presionada) la tecla Control (Ctrl) y entonces teclee la letra c, para detener el programa. Escriba un programa correcto. Nombre del programa: suma_while.py. Hay dos formas bsicas de encontrar errores en el programa: (a) Lea el programa cuidadosamente y piense en las consecuencias de cada instruccin (b) Imprima resultados intermedios y compare con los clculos manuales Primero, intente el mtodo (a) y encuentre tantos errores como pueda. Entonces, intente el mtodo (b) para M = 3 y compare la evolucin de s con sus propios clculos manuales. Nota: Una forma pythonica de resolver este problema es mediante:
print(sum(1.0/k for k in xrange(1, M+1, 1)))
19
1.0
0.5
0.0
0.5
1.0 8
Suponga que desea calcular la funcin seno inversa: arcsin(x). El mdulo numpy tiene una funcin para calcular dicha funcin, pero cul es el nombre de esta funcin? Graque esta funcin en el dominio adecuado. 6. Sea:
q = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h']]
q[-1][-2]
tiene el valor g.
index_nested_list.py
7. Construya un doble loop sobre una lista anidada. Considere la lista del ejercicio 6. Es posible visitar todos los elementos de q usando el siguiente for loop anidado:
for i in q: for j in range(len(i)): print i[j]
y j?
20
for
0 x N (x) = 2x 0
si si si si
10. Un desarrollo en serie de Fourier para la funcin dada por: 0, si 0 < t < 2 t 2 , si 2 < t < f (t) = 3 3 t, si < t < 2 2 3 0, si < t < 2 2 donde el periodo es T = 2 , est dado por: a0 = an = 4
( n )] 2 [ n ( 1) cos n2 2 bn = 0
21
22
CAPTULO
Grcas
# Se obtiene una ejecucion mas rapida (y la sintaxis tambien es mas simple) # actuando sobre todo el arreglo t y = f(t) plot(t, y) xlabel("t") ylabel("y") legend(["t^2*exp(t^2)"]) show()
23
0.40 0.35 0.30 0.25 0.20 0.15 0.10 0.05 0.00 0.0 0.5 1.0 1.5 t 2.0 y
t^2*exp(t^2)
2.5
3.0
Descarga el manual de matplotlib de http://matplotlib.org/contents.html (o use directamente el link http://matplotlib.org/Matplotlib.pdf) y estudia el tutorial de pyplot. 1. Graca la funcin f (x) = x3 en color rojo, con lneas punteadas, en el intervalo de 5 a 5. 2. Modica el grueso de la lnea de la grca anterior a 2.0. 3. Graca las funciones seno y coseno en el rango de [, ] utilizando el comando subplot()
donde k , c y r son constantes, ha demostrado ser un modelo exacto de crecimiento para poblaciones de protozoarios, bacterias, moscas de fruta o animales connados a espacios limitados. Este modelo muestra un crecimiento acotado. Ms especcamente, la problacin predicha por (2.1) no aumentar ms all del nmero K , llamado capacidad lmite o de soporte del sistema. Para r < 0, ert 0 y P (t) 0 cuando t .
24
Captulo 2. Grcas
2.1.2 Prctica 5
Un alumno enfermo de un virus de catarro regresa a un colegio aislado, de 2 000 estudiantes. La cantidad de estudiantes infectados con catarro, t das despus del regreso del alumno enfermo, se calcula con la funcin logstica P (t) = 2000 1 + 1999e0.8905t
1. De acuerdo con este modelo, cuntos estudiantes sern infectados por el catarro despus de 5 das? Para responder a esta pregunta, basta con calcular P (5) = 82.348 (en realidad son 83 estudiantes). Esto clculo puede hacerse con una calculadora, o con el siguiente cdigo:
import numpy as np def p(t): return 2000.0/(1.0 + 1999.0*np.exp(-0.8905*t)) print(p(5))
2. Cunto tiempo pasar para que la mitad de la poblacin de estudiantes quede infectada? Para responder a esta pregunta de manera exacta, se puede despejar t de la ecuacin: 1000 = 2000 1 + 1999e0.88905t
cuya solucin es t = ln(1999)/0.8905 8.535 das. Esto puede responderse de manera aproximada utilizando una grca. 3. Cuntos alumnos indica el modelo que se infectarn despus de un tiempo muy prolongado? El modelo indica que se infectarn todos los estudiantes. 4. Trace una grca de P (t).
import matplotlib.pyplot as plt import numpy as np t = 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.6 fig.set_size_inches( (size[0]*scale, size[1]*scale) ) plt.show()
25
Ahora veremos la misma grca con una escala logartmica en el eje vertical:
import matplotlib.pyplot as plt import numpy as np t = 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.6 fig.set_size_inches( (size[0]*scale, size[1]*scale) ) plt.show()
26
Captulo 2. Grcas
27
3 2 1 0 1 2 33 2 1 0 1 2 3
2.3 Grcas en 3D
2.3.1 Prctica 6
(surface3ddemo.py)
from mpl_toolkits.mplot3d import Axes3D from matplotlib import cm from matplotlib.ticker import LinearLocator, FormatStrFormatter import matplotlib.pyplot as plt import 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
Captulo 2. Grcas
6 4
2 0
6 6
1.01 0.79 0.56 0.34 0.11 -0.11 -0.34 -0.56 -0.79 -1.01 6
2.4 Ejercicios
1. Conduccin electroltica en las rocas (Ley de Archie). La resistividad elctrica de un cilndro slido de longitud L y seccin transversal A, con resistencia R entre sus dos caras, est dado por: =R A L
Debido a que la mayora de las rocas son pobres conductores, sus resistidades seran muy grandes si no fuera por el hecho de que son usualmente porosas y que los poros estn llenos con uidos, principalmente agua. Como resultado, las rocas son conductores electrolticos, cuya resistividad efectiva puede denirse por la frmula anterior, donde la propagacin de la corriente se da mediante conduccin inica (por molculas que tienen un exceso o deciencia de electrones). Por lo tanto la resistividad vara con la movilidad, concentracin y grado de disociacin de los iones (esta ltima depende de la constante dielctrica del solvente). El ujo de corriente no solamente es lento comparado con la conduccin ohmica, sino que implica un transporte real de material, normalmente resultando en transformacin qumica. 2.4. Ejercicios 29
La conductividad de una roca porosa vara con el volumen y el arreglo de los poros y ms an con la conductividad y la cantidad de agua contenida. De acuerdo con la frmula emprica obtenida por Archie (1942): e = am S n W
donde es la fraccin de volumen poroso (porosidad), S es la fraccin 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 1.5 e = 2 W
Utilice una grca con escalas logartmicas para gracar la frmula anterior para valores de = 0.01, 0.1, 0.3, 0.5. 2. Vida media del plutonio. Un reactor de cra convierte uranio 238 relativamente estable en el istopo plutonio 239. Despus de 15 aos, se ha determinado que 0.043% de la cantidad inicial de A0 de plutonio se ha desintegrado. (a) Determine la vida media de ese istopo, si la razn de desintegracin es proporcional a la cantidad que queda. (b) Graque A(t) si A0 = 1.0 kg. Verique grcamente la respuesta del inciso anterior.
La siguiente gura utiliza echas para indicar la direccin 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 - b axis([l - 0.05*dx, r + 0.05*dx, b - 0.05*dy, t + 0.05*dy]) colorbar() show()
30
Captulo 2. Grcas
7 6 5 4 3 2 1 0 0 1 2
2m s
Ahora se utilizan lneas de fuerza para indicar la direccin de campo. El color est asociado a la magnitud del campo.
import numpy as np from numpy import pi import 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()
31
6 5 4 3 2 1 00 1 2 3 4 5 6
2.5.1 Ejercicio
Representa el campo vectorial siguiente de las dos maneras ejemplicadas anteriormente. ( ) ( ) = sin y A sin x 2 2
32
Captulo 2. Grcas
CAPTULO
lgebra lineal
Esto produce el resultado correcto, pero si a y b contienen cada uno un milln de nmeros, pagaremos el precio por las ineciencias de los ciclos en Python. Podramos conseguir la misma tarea mucho ms rpido en C al escribir (por simplicidad no escribimos las declaraciones de variables, inicializaciones, la reservacin del espacio de memoria, etc.).
for (i = 0; i < numero_elementos; i++) { c[i] = a[i]*b[i]; }
casi a la misma velocidad que con C, pero con la simplicidad en la programacin que se espera de cdigo escrito en Python.
33
#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 space N = 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 space free ( X ); free ( Y ); } int main(int argc, const char * argv[]) { runSDOTSample(); return 0; }
3.1.2 Prctica 4
Imagine que desea sumar dos vectores llamados a y b. El vector a contiene los cuadrados de los enteros 0 hasta n (excluyendo n); por ejemplo, si n = 3, entonces a = (0, 1, 4). El vector b contiene los cubos de los enteros 0 hasta n (excluyendo n); por ejemplo, si n = 3, entonces b = (0, 1, 8). Cmo hara eso con Python nicamente? Sumando vectores utilizando Python puro La siguiente funcin 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 ** 2 b[i] = i ** 3 c.append(a[i] + b[i]) return c
Sumando vectores utilizando NumPy La siguiente funcin resuelve el mismo problema con NumPy:
34
Comparando los tiempos de ejecucin Con ayuda del siguiente cdigo, compare los tiempos de ejecucin para n = 1000, 2000, 3000. Ejecute su programa desde la lnea de comandos.
import sys from datetime import datetime import numpy def numpysum(n): a = numpy.arange(n) ** 2 b = numpy.arange(n) ** 3 c = a + b return c def pythonsum(n): a = range(n) b = range(n) c = [] for i in range(len(a)): a[i] = i ** 2 b[i] = i ** 3 c.append(a[i] + b[i]) return c size = int(sys.argv[1]) start = datetime.now() c = pythonsum(size) delta = datetime.now() - start print("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() - start print("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 de ejecucin (en microsegundos) obtenidos en mi mquina para algunos valores de size (la segunda columna corresponde a la funcin que utiliza listas y la tercera, a la funcin que utiliza arreglos de NumPy): size 10 100 1000 10000 Tiempo (pythonsum) 20 66 622 5468 Tiempo (numpysum) 50 52 78 369
35
Adems del tipo de los elementos del arreglo, tambin 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 el tamao del arreglo en cada dimensin. 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 tamao 3 3 con los siguientes elementos 0 1 2 3 4 5 6 7 8 Compruebe que tambin puede crearlo de la siguiente manera:
>>> m3 = arange(9).reshape(3, 3)
Cul es la salida de
m3[2, 1]?
36
La funcin inv del paquete numpy.linalg puede invertir una matriz por nosotros. Vamos a resolver un ejemplo: 1. Crea la matriz A con la funcin
mat:
inv:
LinAlgError.
2. Invoque la funcin
solve
3.3 Ejercicios
Instrucciones: Utilice Numpy para resolver los siguientes ejercicios. 3.2 1.5 1. Resuelva las operaciones indicadas, suponiendo que u = 0.6, v = 4.1 1.4 0.2 (a) u v (b) u (c) 3 v u 3.3. Ejercicios 37
(d) u v 2. Encuentre la solucin del sistema de ecuaciones lineales dado por las matrices aumentadas 0 2 3 8 1 5 (a) 2 3 1 1 2 5 1 1 1 1 4 1 2 3 4 10 (b) 1 3 6 10 20 1 4 10 20 35 3. Utilice la funcin numpy.linalg.eig para encontrar los eigenvalores y eigenvectores de la matriz cua 1 0 2 drada A = 3 1 3 2 0 1
38
CAPTULO
Polinomios e interpolacin
Interpole entre log 4.5 = 0.6532125 y log 5.5 = 0.7403627. Ajuste con un polinomio de interpolacin de Lagrange de tercer orden para estimar log 5 utilizando los datos anteriores.
39
40
0.5
0.0
0.5
1.0
41
42
CAPTULO
Ajuste de funciones
donde a0 y a1 son coecientes 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 expresin anterior como: e = y a0 a1 x (5.1)
As, el error o residuo es la discrepancia entre el valor real de y y el valor aproximado, a0 + a1 x, predicho por la ecuacin lineal. En la regresin lineal por mnimos cuadrados, la estrategia es (como su nombre lo indica), minimizar la suma de los cuadrados de los residuos entre la y medida y la y calculada con el modelo lineal: Sr =
n i=1
e2 i =
n i=1
(yi a0 a1 xi )
(5.2)
donde n es el nmero de pares de observaciones. Ecuaciones normales (regresin lineal) Para determinar los valores de a0 y a1 que minimizan la Ec. (5.2), esta ltima es diferenciada parcialmente con respecto a cada coeciente e igualando cada expresin resultante a cero. Como resultado se tienen las
43
ecuaciones normales:
( ) na0 + x i a1 = yi ( ) ( ) xi a0 + x2 xi yi i a1 =
(5.3) (5.4)
44
0.5
1.0
1.5
2.0
2.5
3.0
donde z0 , z1 , . . ., zm son las m + 1 funciones diferentes. La regresin lineal simple y mltiple encajan dentro de este modelo: z0 = 1, z1 = x1 , . . ., zm = xm . Adems la regresin de polinomios se incluye tambin si las z son monomios simples como en z0 = x0 = 1, z1 = x, . . ., zm = xm . Observe que la terminologa lineal se reere slo a la dependencia del modelo sobre sus parmetros (es decir, las a). Como en el caso de regresin de polinomios, las mismas funciones pueden ser altamente no lineales. La ecuacin (5.5) puede se puede expresar en notacin 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
45
independientes z01 z02 Z= . . . z0n z11 z12 . . . z1n .. . zm1 zm2 . . . zmn
donde m es el nmero de variables del modelo y n es el nmero de datos. Como n m + 1, la mayora de las veces Z no es una matriz cuadrada. El vector columna Y contiene los valores observados de la variable dependiente: y1 y2 Y = . . . yn
La suma de los cuadrados de los residuos para este modelo se puede denir como
n i=1
Sr =
e2 i =
n i=1
yi
m j =0
2 aj zji
Esta cantidad se puede minimizar al tomar su derivada parcial con respecto a cada uno de los coecientes y jar los resultados de la ecuacin igual a cero. La salida de este proceso son las ecuaciones normales que se pueden expresar brevemente en forma de matriz como Z T ZA = Z T Y Ejemplo 2: Regresin polinomial (de segundo orden) Ajustar a una parbola los datos siguientes: (5.7)
46
xi 0 1 2 3 4 5
(5.8)
Podemos denir una funcin 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)])
x = np.arange(6)
N = 2
4 16] 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
numpy.linalg.lstsq,
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)
47
Interprete los resultados anteriores y graque los datos junto con el resultado obtenido de la regresin polinomial
48
CAPTULO
49
60 50 40 30 20 10 0 100 2 4 6 8 10 12 14 16 18
Puede notarse que la solucin est entre 14 y 16. Si graca en ese intervalo, puede notarse un poco mejor la raz.
import numpy as np import matplotlib.pyplot as plt c = np.linspace(14.0, 16.0) f = 667.38*(1 - np.exp(-0.146843*c))/c - 40 plt.plot(c, f) plt.grid() plt.show()
50
2.0 1.5 1.0 0.5 0.0 0.5 1.0 1.5 2.0 2.5 14.0 14.5 15.0 15.5 16.0
Se puede utilizar Scipy para encontrar las races de manera numrica, con mucha simplicidad. A continuacin se muestra cmo se resuelve el problema anterior con el mtodo de biseccin, uno de los ms simples para encontrar races de ecuaciones no lineales.
import numpy as np from 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 raz real ms grande de h(x) = 2x3 11.7x2 + 17.7x 5 (a) En forma grca.
import numpy as np import matplotlib.pyplot as plt x = np.linspace(0.0, 4.0) h = ((2*x - 11.7)*x plt.plot(x, h) + 17.7)*x - 5.0
51
plt.grid() plt.show()
import numpy as np import matplotlib.pyplot as plt x = np.linspace(3.5, 3.6) h = ((2*x - 11.7)*x plt.plot(x, h) plt.grid() plt.show() + 17.7)*x - 5.0
52
0.6 0.4 0.2 0.0 0.2 0.4 0.6 0.8 3.50 3.52 3.54 3.56 3.58 3.60
Puede notarse que la raz ms grande es aproximadamente 3.56. (b) Con el mtodo de Newton-Raphson (tres iteraciones, x0 = 3, = 0.001). Este mtodo es una aproximacin a una raz de f (x) = 0 a partir del valor inicial p0 mediante la iteracin: pk = pk1 f (pk1 ) f (pk1 )
Un algoritmo para el mtodo de Newton-Raphson se obtiene fcilmente al sustituir la ecuacin anterior por la frmula predictiva x = g (x) en el algoritmo de punto jo. Observe, sin embargo, que el programa tambin debe modicarse para calcular la primera derivada. Considerando varios problemas potenciales con el mtodo de Newton Raphson, el programa se podra mejorar incorporando algunas consideraciones adicionales (ver pg. 153, 154 del libro Mtodos numricos 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 iteracin. # 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 trminos consecutivos
53
# P es la sucesin {pn} completa # k es el nmero de iteraciones realizadas # P[k] es la aproximacin al punto fijo P = zeros(numMaxIteraciones + 1) P[0] = p0 for k in range(1, numMaxIteraciones + 1): gk = P[k - 1] - g(P[k - 1])/dg(P[k - 1]) P[k] = gk err = 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): break if (k == numMaxIteraciones): print('Se ha excedido el numero de iteraciones') return P, k, errorRelativo def h(x): return ((2*x - 11.7)*x 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) + 17.7)*x - 5.0
newton
del mdulo
scipy.optimize.
+ 17.7)*x - 5.0
return (6.0*x - 23.4)*x + 17.7 from scipy.optimize import newton zero = newton(h, 3.0, dh) print(zero)
54
* * * * * * * * * * *
+ Estructura parametros_cuadratica. Esta estructura almacena los coeficientes {a, b, c} de un polinomio cuadrtico ax^2 + bx + c como nmeros de tipo double. Declaracin de prototipos de funciones para + Evaluar un polinomio cuadrtico, dado por los parmetros apuntados por params, en un valor x (cuadratica) + Evaluacin de la derivada del polinomio cuadrtico (deriv_cuadratica) + Evaluacin simultnea 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);
55
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 cdigo fuente anteriores para encontrar la raz del polinomio cuadrtico x2 5 = 0:
/* * ===================================================================================== * * * * * * * */ #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 iteracin del mtodo */ int iter = 0; /* Contador de iteraciones */ const int MAX_ITER = 100; /* Nmero mximo 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 raz */ double raiz_esperada = sqrt (5.0); /* Valores iniciales de los limites del intervalo de bsqueda */ double x_inferior = 0.0, /* * Estructura capaz de apuntar a * * */ gsl_function F; struct parametros_cuadratica params = {1.0, F.function = &cuadratica; F.params = ¶ms; /* Se utiliza el mtodo de biseccin. 0.0, -5.0}; + la funcin cuya raz desea encontrarse + los parmetros que necesita la funcin x_superior = 5.0; Compilar con: Descripcin: Ejemplo del uso de rutinas de GSL para encontrar las races de funciones unidimensionales arbitrarias. icc demo_root.c -lgsl -o demo_root Nombre del archivo: demo_root.c
* =====================================================================================
56
* NOTA: Se pueden seleccionar entre diferentes tipos de solucionadores. * */ 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 funcin F y * el intervalo inicial de bsqueda [x_inferior, */ gsl_root_fsolver_set (s, &F, x_inferior, x_superior); /* Imprimir el nombre del mtodo usado */ printf ("Usando el mtodo %s\n", printf ("%5s [%9s, "iter", /* * Iterar mientras que * el estado sea GSL_CONTINUE y * no se haya alcanzado el nmero mximo de iteraciones */ do { iter++; /* Incrementar en uno el contador de iteraciones */ /* * Lleva a cabo una iteracin del solucionador s. * Si la iteracin encuentra un error inesperado, la variable estado * contiene un cdigo de error */ estado = gsl_root_fsolver_iterate (s); /* Actualiza la mejor estimacin de la raz que se tiene al momento */ r = gsl_root_fsolver_root (s); /* Actualiza los lmites del mejor intervalo que encierra una posible raz */ x_inferior = gsl_root_fsolver_x_lower (s); x_superior = gsl_root_fsolver_x_upper (s); /* * Verificar la convergencia del mtodo en el intervalo con * error absoluto = 0.0 * error relativo = 0.001 * El test devuelve GSL_SUCCESS si el mtodo ha convergido */ estado = gsl_root_test_interval (x_inferior, if (estado == GSL_SUCCESS) printf ("El mtodo converge:\n"); /* Mostrar informacin sobre la iteracin actual */ printf ("%5d [%.7f, 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); %.7f] %.7f %+.7f %.7f\n", x_superior, 0, 0.001); gsl_root_fsolver_name (s)); /* Imprimir el encabezado de resultados intermedios */ %9s] %9s %10s %9s\n", "superior", "raiz", "err", "err(est)"); "inferior", x_superior] Verifique el manual de la GSL
57
/* Terminar el programa devolviendo el valor de la variable estado */ return estado; } /* ---------Fin de la funcin main ---------- */
58
CAPTULO
Aproximacin a la primera derivada con diferencia hacia atrs f (xi ) = f (xi ) f (xi1 ) + O(xi xi1 ) xi xi1
Aproximacin a la primera derivada con diferencias centradas f (xi ) = ( ) f (xi+1 ) f (xi1 ) + O h2 2(xi+1 xi1 )
59
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.1 Ejemplo 1
Calcule
0 4
x2 dx utilizando
scipy.integrate
from scipy import integrate x2 = lambda x: x**2 integ = integrate.quad(x2, 0.0, 4.0) print integ
inf
para denotar +.
La regla trapezoidal La regla trapezoidal es la ms sencilla de todas las frmulas de integracin cerrada de Newton-Cotes. Geomtricamente, la regla trapezoidal es equivalente a aproximar el rea bajo la curva con la del trapecio bajo la lnea recta que conecta f (a) y f (b) en la Figura Regla trapezoidal . Recuerde que la frmula para calcular el rea de un trapecio es la altura por el promedio de las bases. En nuestro caso, el concepto es el mismo, pero el trapecio est sobre su lado. La regla compuesta del trapecio Un mtodo intuitivo para hallar el rea limitada por una curva y = f (x) en un intervalo [a, b] es dar una aproximacin a dicha rea sumando las reas de una serie de trapecios construidos sobre los intervalos {[xk , xk+1 ]} de una particin de [a, b]. 60 Captulo 7. Diferenciacin e integracin numrica
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 integral x = arange(0, 10, 0.01) y = func(x) plot(x, y, linewidth=1) # make the shaded region ix = 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'))
61
ax.set_yticks([]) show()
Supongamos que se divide el intervalo [a, b] en M subintervalos [xk , xk+1 ] de anchura comn h = (b a)/M mediante una particin cuyos nodos xk = a + kh, para k = 0, 1, . . . , M , estn equiespaciados. La regla compuesta del trapecio con M subintervalos se puede expresar de las siguientes formas equivalentes: T (f, h) = h (f (xk1 ) + f (xk )) 2
M k=1
(7.1)
o bien T (f, h) =
M 1 h (f (a) f (b)) + h f (xk ) 2 k=1
(7.3)
Este valor es una aproximacin a la integral de f (x) en [a, b], lo que se escribe como
a b
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 aproximacin 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 frmula (7.3), los clculos son: ( ) 1 1/2 T f, = (f (1) + f (6)) + 2 2 ( ( ) ( ) ( ) ( ) ( )) 1 3 5 7 9 11 f + f (2) + f + f (3) + f + f (4) + f + f (5) + f 2 2 2 2 2 2 1 = (2.9093 + 1.01735) + 4 1 (2.63815 + 2.30807 + 1.97931 + 1.68305 + 1.43530 + 1.24319 + 1.10831 + 1.02872 + 1.00024) 2 1 1 = (3.92665) + (14.42438) 4 2 = 0.98166 + 7.21219 = 8.19385 Compruebe el resultado anterior manualmente y despus utilizando el siguiente cdigo:
62
from numpy import linspace, sin, sqrt from scipy.integrate import trapz x = linspace(1, 6, 11) y = 2 + sin( 2*sqrt(x) ) T = trapz(y, x) print(T)
63
64
CAPTULO
donde C es la constante de integracin. En esta solucin existe un grado de libertad, dado por la eleccin de la constante de integracin C .
import matplotlib.pyplot as plt import numpy as np num_puntos = 81 t = np.linspace(-2.0, 5.0, num_puntos) num_curvas = 5 y = np.zeros((num_curvas, num_puntos)) for i, C in enumerate(range(-2, num_curvas - 2)): y[i] = plt.grid() plt.show() t + np.exp(-t) + C plt.plot(t, y[i])
65
8 7 6 5 4 3 2 1 0 12 1 0 1 2 3 4 5
A diferencia de la ecuacin diferencial dada, no todas pueden resolverse de manera exacta (ya sea mediante integracin directa o por alguno de los mtodos tradicionales). A menudo se da el caso de que no hay una solucion analtica conocida, por lo que necesitamos aproximaciones numricas. A modo de ejemplo, consideremos, en el contexto de la dinmica de poblaciones, un sistema no lineal que es una modicacin de las ecuaciones de Lotka-Volterra x = f (t, x, y ) = x xy 1 2 x 10 1 y = g (t, x, y ) = xy y y 2 20
para 0 t 30 con la condicin inicial x(0) = 2 e y (0) = 1. La solucin numrica se consigue con el siguiente cdigo:
import matplotlib.pyplot as plt import numpy as np from scipy.integrate import odeint x0 = [2, 1] def f(xVec, t): x, y = xVec f0 = x - x*y - x**2 / 10.0 f1 = x*y - y - y**2 / 20.0 return [f0, f1]
66
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)
2 50+t
dt
(8.2)
Multiplicando la Ec. (8.1) por el factor integrante (8.2) ( ) dA 2 2 (50 + t) + A = 3(50 + t)2 dt 50 + t ] d [ (50 + t)2 A , por lo que tenemos la expresin ms simple: dt ] d [ (50 + t)2 A = 3(50 + t)2 dt
que hay que resolver por integracin de ambos miembros: (50 + t)2 A = 3 (50 + t)2 dt = (50 + t)3 + C
Sustituyendo la condicin inicial A(0) = 10, en la expresin anterior, obtenemos C = 100000. La solucin de la Ec. (8.1) es: A(t) = 50 + t 100000 (50 + t)2
67
Por lo tanto, a los 30 min., la cantidad de sal disuelta en el tanque es A(30) = 64.375 lb. Resuelva de manera numrica el problema. Graque la solucin exacta junto con la solucin numrica, hasta los 35 min.
(8.3)
donde c, 0 y son nmeros reales positivos. Considremos el caso en que c < 0 , que corresponde a un sistema sub-amortiguado. Adems suponga que < 0 . Con estas suposiciones, la solucin general de (8.3) se puede expresar como y = yu + yd , donde ( ) ( ) 2 c2 + C ect sin t 2 c2 (8.4) yu = C1 ect cos t 0 2 0 yd = F0 M ( ) sin[t + ( )] C1 , C2 dependen de las condiciones iniciales y 1 M ( ) = 2 (0 2 )2 + 4c2 2 ( ) 2c ( ) = arctan < ( ) < 0 2 2 0 Ejemplo El sistema y +y + 4y = 12 sin t (8.6) (8.7) (8.5)
con c = 1/2, 0 = 2, = 1, sujeto a las condiciones iniciales y (0) = 0, y (0) = 0 tiene la solucin [ ( ) ( )] 15 2 15 6 t/2 6 y (t) = e cos t 15 sin t + 10 sin(t 0.32175) 5 2 5 2 5
import matplotlib.pyplot as plt import numpy as np tfinal = 20.0 num_puntos = tfinal * 100 + 1 t = np.linspace(0.0, tfinal, num_puntos) theta = np.sqrt(15)*t/2.0 yu = 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 + yd plt.plot(t, y) plt.grid() plt.show()
68
4 3 2 1 0 1 2 3 40 5 10 15 20
Una solucin numrica de este problema, utilizando un mtodo de Runge-Kutta de orden (4)5 debido a Dormand y Prince (con control del tamao de paso y salida densa) est dada por el siguiente cdigo:
import matplotlib.pyplot as plt import numpy as np from scipy.integrate import ode from math import sin y0 = [0, 0] t0 = 0 def f(t, y, c, omega0, F0, omega): x, v = y xDot = v vDot = -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.0 t = np.linspace(0.0, t1, t1*100 + 1)
69
dt = t[1] y = np.zeros(len(t)) y[0] = y0[0] i = 1 while r.successful() and r.t <= t1: r.integrate(r.t + dt) t[i] = r.t y[i] = r.y[0].real i += 1 plt.plot(t, y) plt.grid() plt.axis([0.0, 20.0, -4.0, 4.0]) plt.show()
donde xn es la posicin de la nave (relativa a la Tierra); mT , la masa de la Tierra; G, la constante de Gravitacin Universal; mL , la masa de la Luna; xL es la posicin de la Luna. Una grca de la ruta seguida por la nave debe verse similar a la siguiente:
70
71
72
CAPTULO
ndices y tablas
73