Tema5 Equation-Solutions CV Examples
Tema5 Equation-Solutions CV Examples
2. Autovalores y autovectores 29
2.1. Descomposición QR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.1.1. Ejemplo 5.12: estudiando la descomposición QR . . . . . . . . . . . . . . . . . 30
2.2. Descomposiciones QR sucesivas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.3. Algoritmo QR para el cálculo de autovectores y autovalores . . . . . . . . . . . . . . 33
2.3.1. Ejemplo 5.13: calculando autovalores y autovectores . . . . . . . . . . . . . . 33
2.3.2. Autovalores y autovectores en python . . . . . . . . . . . . . . . . . . . . . . . 35
2.3.3. Ejercicio 5.2: Pozo de potencial asimétrico en Mecánica Cuántica . . . . . . . 36
3. Ecuaciones no lineales 38
3.1. Método del punto fijo o relajación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.1.1. Ejemplo 5.14: aplicando el método del punto fijo . . . . . . . . . . . . . . . . . 39
3.1.2. No convergencia del método del punto fijo . . . . . . . . . . . . . . . . . . . . 40
3.1.3. Limitaciones del método del punto fijo . . . . . . . . . . . . . . . . . . . . . . 42
3.1.4. Convergencia y estimación del error del método del punto fijo/relajación . . 43
3.1.5. Ejercicio 5.3: propagación de epidemias . . . . . . . . . . . . . . . . . . . . . . 45
3.1.6. El método del punto fijo sobrerelajado . . . . . . . . . . . . . . . . . . . . . . . 45
3.1.7. Método del punto fijo o relajación con más de una variable . . . . . . . . . . . 46
3.2. Método de la bisección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
1
3.2.1. Algoritmo para el método de la bisección . . . . . . . . . . . . . . . . . . . . . 48
3.2.2. Convergencia del método de la bisección . . . . . . . . . . . . . . . . . . . . . 49
3.2.3. Limitaciones del método de la bisección . . . . . . . . . . . . . . . . . . . . . . 49
3.2.4. Ejemplo 5.17: visualizando el método de la bisección . . . . . . . . . . . . . . 51
3.2.5. Ejercicio 5.6: la constante de desplazamiento de Wien . . . . . . . . . . . . . . 54
3.3. Método de Newton-Raphson . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.3.1. Error y convergencia del método de Newton-Raphson . . . . . . . . . . . . . 56
3.3.2. Desventajas del método de Newton-Raphson. . . . . . . . . . . . . . . . . . . 58
3.3.3. Ejemplo 5.18: visualizando el método de Newton-Raphson . . . . . . . . . . . 58
3.3.4. Ejercicio 5.7: función arcotangente hiperbólica . . . . . . . . . . . . . . . . . . 60
3.3.5. Ejercicio 5.8: las raíces de un polinomio . . . . . . . . . . . . . . . . . . . . . . 60
3.3.6. Método de la secante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
3.3.7. Método de Newton-Raphson para más de una variable . . . . . . . . . . . . . 61
5. Ejercicio adicionales 81
5.1. Ejercicio 5.11: minimizando el potencial de ionización (Examen de Enero de 2023) . . 81
5.2. Ejercicio 5.12: funciones complejas con polos (Examen de Junio de 2023) . . . . . . . 81
5.3. Ejercicio 5.13: cuadrando posiciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
5.4. Ejercicio 5.14: teoría del campo medio para el ferromagnetismo . . . . . . . . . . . . 84
5.5. Ejercicio 5.15: potencial cuadrado cuántico . . . . . . . . . . . . . . . . . . . . . . . . 84
5.6. Ejercicio 5.16: el punto de Lagrange Tierra-Luna . . . . . . . . . . . . . . . . . . . . . 86
5.7. Ejercicio 5.17: ajustando el fondo cósmico de microondas . . . . . . . . . . . . . . . . 87
2
a11 x1 + a12 x2 + · · · + a1n xn = b1 ,
a21 x1 + a22 x2 + · · · + a2n xn = b2 ,
.. .. .. ..
. . . .
an1 x1 + an2 x2 + · · · + ann xn = bn ,
(1)
o en formulación matricial:
A · X = B,
con
a11 a12 ··· a1n x1 b1
a21 a22 ··· a2n x2 b2
A= , X= y B= .
.. .. .. .. .. ..
. . . . . .
an1 an2 · · · ann xn bn
X = A−1 · B,
a11 a12 ··· a1n | b1
a21 a22 ··· a2n | b2
( A| B) =
.. .. .. .. ..
. . . . | .
an1 an2 · · · ann | bn
3
Operaciones elementales sobre la matriz extendida:
1. Multiplicar una fila por un escalar (no nulo).
2. Sumar a una fila el múltiplo de otra.
3. Intercambiar las posición de dos filas.
El método de Gauss combina las operaciones 1 y 2 para transformar:
a11 a12 a31 ··· a1n | b1 1 ā12 ā31 ··· ā1n | b̄1
a21 a22 a32 ··· a2n | b2
0 1 ā32 ··· ā2n | b̄2
( A| B) =
a31 a32 a33 ··· a3n | b3 ⇒
0 0 1 ··· ā3n | b̄3
.. .. .. .. .. .. .. .. .. .. .. ..
. . . . . | . . . . . . | .
an1 an2 an3 · · · ann | bn 0 0 0 ··· 1 | b̄n
2 w + x + 4 y + z = − 4,
3 w + 4 x − y − z =3,
w − 4 x + y + 5 z =9,
2 w − 2 x + y + 3 z =7.
(2)
4
[7]: from numpy import array,zeros,column_stack,dot
def gaussian_elim(A,B):
# Calculamos el número de filas
N=len(B)
AB=column_stack((A,B))
# Eliminación gaussiana
for m in range(N):
# 3. Sustitución inversa
x=zeros(N,float)
for m in range(N-1,-1,-1):
x[m]=AB[m,N]
for i in range(m+1,N):
x[m]-=AB[m,i]*x[i]
return x,AB
AB=column_stack((A,B))
print("Nuestra matriz extendida inicial")
print(AB)
print("")
x,AB2=gaussian_elim(A,B)
5
print("La solución del sistema de ecuaciones es:")
print(x)
print("")
6
x + 4 y + z = − 4,
3 w + 4 x − y − z =3,
w − 4 x + y + 5 z =9,
2 w − 2 x + y + 3 z =7.
(3)
def gaussian_pivot(A,B):
AB=column_stack((A,B))
for m in range(N):
#1. Escogemos la fila i>=m cuyo elemento a_{im} este más alejado de 0.
pivot= m
largest= abs(AB[m,m])
for i in range(m+1,N):
if abs(AB[i,m]>largest):
largest=AB[i,m]
pivot=i
7
# 5. Sustitución inversa
x=zeros(N,float)
for m in range(N-1,-1,-1):
x[m]=AB[m,N]
for i in range(m+1,N):
x[m]-=AB[m,i]*x[i]
return x,AB
AB=column_stack((A,B))
x,AB2 = gaussian_pivot(A,B)
8
[ 1.61904762 -0.42857143 -1.23809524 1.38095238]
1.3. Factorización LU
La eliminación gaussiana con pivote es un método efectivo y rápido.
Sin embargo, en muchas ocasiones en física queremos resolver el sistema:
A · X = V,
1 0 ··· 0
0 α ··· 0
I1 (n, 2) = .
.. .. . .
. . . 0
0 0 ··· 1
2. Sumar a una fila k la fila m multiplicada por un escalar.
Por ejemplo, restar a la segunda fila la primera multiplicada por α.
1 0 ··· 0
−α 1 · · · 0
I2 (n, 2, 1) = .
.. .. . .
. . . 0
0 0 ··· 1
3. Intercambiar la fila k por la fila m.
Por ejemplo, intercambiar la fila 2 por la fila 1.
0 1 ··· 0
1 0 ··· 0
I3 (n, 1, 2) = .
.. .. . .
. . . 0
0 0 ··· 1
9
Definidas esas operaciones. Se puede construir para cada uno de los pasos de la eliminación
gaussiana la matriz que nos permite transforma A en una matriz diagonal.
a11 a12 a13 a14
a21 a22 a23 a24
A=
a31
a32 a33 a34
a41 a42 a43 a44
definir las matrices asociadas a las 4 operaciones necesarias para convertirla en una matriz trian-
gular superior.
1. Dividir la primera fila por su primer elemento y restarsela al resto de filas al multipicarla
por α j1 con j>1.
1 0 0 0
L1 =
1 − a21 a11 0 0 ,
a11 − a31 0 a11 0
− a41 0 0 a11
que permite
1 b12 b13 b14
0 b22 b23 b24
L1 · A = =B
0 b32 b33 b34
0 b42 b43 b44
2. Dividir la segunda fila por su segundo elemento y restarsela al resto de filas al multipicarla
por β j2 con j>2.
b22 0 0 0
1 0 1 0 0
L2 = ,
b22 0 −b32 b22 0
0 −b42 0 b22
que permite
1 c12 c13 c14
0 1 c23 c24
L2 · B = =C
0 0 c33 c34
0 0 c43 c44
3. Dividir la tercera fila por su tercer elemento y restarsela al la cuarta fila multiplicada por c43 .
10
c33 0 0 0
1 0 c33 0 0
L3 = ,
c33 0 0 1 0
0 0 −c43 c33
que permite
1 d12 d13 d14
0 1 d23 d24
L3 · C = =D
0 0 1 d34
0 0 0 d44
4. Dividir la cuarta fila por su cuarto elemento.
d44 0 0 0
1 0 d 44 0 0
L4 = ,
d44 0 0 d44 0
0 0 0 1
1.3.2. Matrices L y U
Por tanto, para una matriz con n filas, necesitamos definir n matrices Li con i = 1, · · · , n.
Una vez obtenidas el problema reside en operar con ellas sobre la matriz extendida y realizar
la sustitución hacía atrás:
Ln · · · L2 · L1 · A · X = Ln · · · L2 · L1 · V,
L = L1−1 L2−1 · · · L−
n
1
y U = Ln · · · L2 · L1 · A,
L · U = A, ⇒ L·U·X = V
11
Ejemplo 5.4: cálculo de L Calcular el valor de L para la matriz del ejercicio 5.3
1. Calculamos la inversa de cada una de las matrices elementales.
a11 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0
a21 1 0 0 0 b22 0 0 0 1 0 0 0 1 0 0
L1−1 =
a31
, L2−1 =
0 b32
, L3−1 = , L4−1 =
0 1 0 1 0 0 0 c33 0 0 0 1 0
a41 0 0 1 0 b42 0 1 0 0 c43 1 0 0 0 d44
2. Operamos con todas ellas:
a11 0 0 0
a21 b22 0 0
L = L1−1 L2−1 L3−1 L4−1 =
a31 b32 c33 0 .
1.3.3. La matriz L
Pero no es necesario:
• la matriz L es la matriz triangular cuyas columnas se generan en cada paso al convertir
la matriz A en una matriz triangular superior, es decir, cuando se calcula U.
La matriz L es una matriz diagonal inferior mientras que la matriz U es una matriz diagonal
superior.
Por tanto, cada una de ellas puede resolverse por medio de la sustitución, hacía atrás para U
y hacía adelante para L.
Específicamente, queremos resolver:
L · U · X = V,
U·X =Y
y el problema:
L · Y = V.
12
N=len(A)
# Creamos la matrix L
for m in range(N):
L[m:N,m] = U[m:N,m] # para cada iteracción (para cada fila),
# la columna m de L queda fijada por el valor que␣
,→tiene U.
return L,U
A=array([[2,1,4,1],[3,4,-1,-1],[1,-4,1,5],[2,-2,1,3]],float)
[[ 2. 0. 0. 0. ]
[ 3. 2.5 0. 0. ]
13
[ 1. -4.5 -13.6 0. ]
[ 2. -3. -11.4 -1. ]]
[[ 1. 0.5 2. 0.5]
[ 0. 1. -2.8 -1. ]
[-0. -0. 1. -0. ]
[-0. -0. -0. 1. ]]
[[ 2. 1. 4. 1.]
[ 3. 4. -1. -1.]
[ 1. -4. 1. 5.]
[ 2. -2. 1. 3.]]
[[ 2. 1. 4. 1.]
[ 3. 4. -1. -1.]
[ 1. -4. 1. 5.]
[ 2. -2. 1. 3.]]
def LU_sol(L,U,V):
for m in range(N):
y[m]=V[m]
for i in range(m):
y[m]-= L[m,i]*y[i]
y[m]/=L[m,m]
for m in range(N-1,-1,-1):
x[m]=y[m]
for i in range(m+1,N):
x[m]-=U[m,i]*x[i]
return(x)
[16]: V=array([-4,3,9,7],float)
print(LU_sol(L,U,V))
14
[ 2. -1. -2. 1.]
[ ]:
Como era de esperar python ya tiene incorporada una rutina para resolver un sistema de
ecuaciones.
La descomposición LU se usa en la función solve del módulo linalg del paquete numpy.
N + ( N − 1) · 2N = N (2N − 1).
2. Para la segunda fila, repetimos el procedimiento pero empezando en la segunda columna:
N − 1 + ( N − 2) · 2( N − 1) = ( N − 1) · (2N − 3).
3. Para la fila i-esima:
N − i + 1 + ( N − i ) · 2( N − i + 1) = ( N − i + 1) · (2 ( N − i ) + 1)) .
4. Sumando todos los términos:
N N
2 N 2
#operaciones LU = ∑ ( N − i + 1) (2 ( N − i) + 1)) = ∑ i (2i − 1) = 3 N 3 + 6
(3N − 1) ∼ N 3 .
3
i =1 i =1
15
1.4. La inversa de una matriz
La matriz de inversa se calcula como:
1
A −1 = [C ] T
det( A)
A · A −1 = I
[21]: A=array([[2,1,4,1],[3,4,-1,-1],[1,-4,1,5],[2,-2,1,3]],float)
L,U=LU(A)
N=len(A)
Ainv=zeros([N,N],float)
for i in range(N):
I=zeros(N,float)
I[i]=1
Ainv[:,i]=LU_sol(L,U,I)
print(dot(A,Ainv))
[[ 1. 0. 0. 0.]
[ 0. 1. 0. 0.]
[-0. -0. 1. 0.]
[-0. 0. 0. 1.]]
Final de la clase del 27/10/21
16
1.5. Matrices tridiagonales y matrices banda
En física es muy común encontrar sistemas de ecuaciones:
A · X = B,
a11 a12
a21 a22 a23
a32 a33 a34
A=
.. .. ..
. . .
an−2n−1 an−1n−1 an−1n
ann−1 ann
17
m ẍ1 = k ( x2 − x1 ) + F1 ,
m ẍi = k ( xi+1 − xi ) + k ( xi−1 − xi ) + Fi , con 1 < i < N,
m ẍ N = k ( x N −1 − x N ) + FN ,
(4)
siendo m la masa de las partículas, k la constante del muelle y Fi cualquier fuerza externa aplicada
sobre la partícula i.
Asumamos ahora que accionamos el sistema al aplicar una fuerza armónica (sinusoidal) sobre la
primera partícula de la forma:
F1 = Cei ω t ,
siendo C una constante y ω la frecuencia de oscilación (empleamos la forma compleja para sim-
plificar los cálculos entendiendo que al final tomaremos la parte real).
La consecuencia de aplicar esta fuerza será que el sistema oscilará con la frecuencia w, de forma
que la posición de cada partícula vendrá dada por:
x i = a i ei ω t ,
−m ω 2 a1 = k ( a2 − a1 ) + C,
− m ω 2 a i = k ( a i +1 − a i ) + k ( a i −1 − a i ), con 1 < i < N,
2
− m ω a N = k ( a N −1 − a N ),
(5)
18
(k − α) a1 − k a2 =C,
−k ai−1 + α ai − k xi+1 =0, con 1 < i < N,
−k a N −1 + (α − k) a N =0,
(6)
(α − k) −k
a1 C
−k α −k a2 0
−k α −k a3 0
· = ,
. .. ... ... .. ..
.
.
−k α −k a N −1 0
−k (α − k) aN 0
1. Para un sistema con N=30 partículas de masa m=1 Kg, ligadas por muelles con constantes
de elasticidad k = 5 N/m, y que sufren una fuerza armónica de módulo 1 N con frecuencia
angular ω = 2 rad/s calcular la posición de cada una de las partículas con respecto a su
posición de equilibrio.
Para ello escribir un programa que optimice la eliminación gaussiana para el caso de tener
una matriz tridiagonal.
2. Generalizar el programa para el caso de tener una matriz banda con up elementos no nulos
por encima de la diagonal y down por debajo.
3. Representar la evolución del sistema por medio de una animación.
[Ayuda: para mayor claridad colocar las partículas en su posición de reposo separadas dos
unidades en una recta].
[38]: # programa que optimiza la eliminación gussiana para matrices tridiagonales.
def tridiagonal_gaussian(A,v):
N=len(v)
for i in range(N-1):
# 1. Dividimos la fila por su primer elemento
# sólo tenemos que hacerlo con el elemento a la derecha
# no hace falta que mandemos el elmento A[i,i] a 1-
# Es suficiente con tenerlo en cuenta al hacer la eliminación hacía␣
,→atrás.
A[i,i+1]/=A[i,i]
v[i]/=A[i,i]
19
A[i+1,i+1]-=A[i+1,i]*A[i,i+1] # no hace falta mandar el elmento␣
,→ A[i+1,i] a cero
v[i+1]-=A[i+1,i]*v[i] # es suficiente asumirlo
# en la sustitución hacía atrás
# 3. Nuestro for va hasta N-2, sólo nos falta operar sobre el último␣
,→elemento de V
v[N-1]/=A[N-1,N-1]
N=30
C=1
m=1
k=5
omega=2
alpha=2*k-m*omega**2
A=zeros([N,N],float)
v=zeros(N,float)
for i in range(N-1):
A[i,i]=alpha # Dado el valor de un elemento de la diagonal.
A[i+1,i],A[i,i+1]=-k,-k # le damos valores al elemento arriba y a la␣
,→izquierda.
A[N-1,N-1]=alpha-k
v[0]=C # El único elemento no nulo de V es el primero.
x=tridiagonal_gaussian(A,v)
20
[40]: from [Link] import plot,show
plot(x)
plot(x,"ro")
show()
[41]: # Para optimizar el código, una matriz a banda con up=2 y down =2 estará escrita␣
,→como:
def band_gaussian(A,v,up,down):
N = len(v)
21
for m in range(N):
for i in range(up):
j = m + up - i
if j<N:
A[i,j] /= div
for k in range(1,down+1):
A[i+k,j] -= A[up+k,m]*A[i,j]
return v
A_band[0,:]=-k
A_band[1,:]=alpha
A_band[2,:]=-k
A_band[1,0]=alpha-k
A_band[1,N-1]=alpha-k
v[0]=C
x2= band_gaussian(A_band,v,1,1)
22
[43]: plot(x2)
plot(x,"ro")
show()
scene=canvas(width=300, height=300,
center=vector(0,0,0))
s=empty(N,sphere)
mu=empty(N,float)
for i in range(N):
mu[i]=2*i-N
s[i]=sphere(pos=vector(mu[i],0,0),radius=0.5)
t=0.0
tmax=20
framerate=30
while t<tmax:
rate(framerate)
t+=1/framerate
for i in range(N):
s[i].pos=vector(mu[i]+x[i]*cos(omega*t),0,0)
23
<[Link] object>
<[Link] object>
<[Link] object>
<[Link] object>
<[Link] object>
<[Link] object>
<[Link] object>
<[Link] object>
A = D+L+U
donde D es diagonal y L/U sólo tiene elementos no nulos por debajo/encima de la diagonal.
Por tanto el sistema de ecuaciones A · x = v se puede escribir como
A · x = (D + L + U) · x = v ⇒ D · x = v − ( L + U ) · x,
24
Definiendo un punto de partida x (0) , por ejemplo x (0) = 0 si no hay más información, obte-
nemos para la estimación k-esima es:
!
1
xik+1 = vi − ∑ aij x kj ,
aii j 6 =i
D −1 · ( L + U ) < 1.
Una condición suficiente pero no necesaria para su convergencia viene dada por la condi-
ción:
Ejemplo 5.9: aplicando el método de Jacobi Aplicar el método de Jacobi al sistema de ecuacio-
nes:
8 w + x + 2 y + z = − 1,
w + 5 x − y − z =3,
w − 4 x + 6y + z =2,
w − 2 x + y + 5 z =1.
(7)
Calcular el número de iteraciones necesarias para obtener una precisión mayor de 10−6 .
def jacobi(A,v,eps):
25
x=(v-dot(LU,x0))/D # iteramos con X
err=max(abs(x-x0))
x0=copy(x)
it+=1
return x,it
[6]: A=array([[8,1,2,1],[1,5,-1,-1],[1,-4,6,1],[1,-2,1,5]],float)
V=array([-1,3,2,1],float)
x1,it=jacobi(A,V,1e-6)
x2,AB=gaussian_elim(A,V)
print(x1,x2,sep=", ")
print("El número de itracciones del método de jacobi es: ",it)
( L + D ) · x = v − U · x,
Por tanto, partiendo de una estimación inicial para x, podemos resolver el sistema exacta-
mente, lo que nos permite acelerar la convergencia del método de jacobi.
!
i −1 N
1
xik+1 = vi − ∑ aij x kj +1 − ∑ aij x kj ,
aii j =1 j = i +1
que converge si
( D + L)−1 · U < 1,
def gauss_seidel(A,v,eps):
26
N=len(v)
# Creamos nuestra descompsición D,L,U
DL=tril(A) # tril crea un matriz triangular inferior
U=A-DL # creamos la matrix U
x0=zeros(N,float) # creamos la primera estimación de x
# inicializamos x
err=1e6
it=0
while err>eps:
x=(v-dot(U,x0))
# Sustitución hacía adelante
for m in range(N):
for i in range(m):
x[m]-= DL[m,i]*x[i]
x[m]/=DL[m,m]
err=max(abs(x-x0))
x0=copy(x)
it+=1
return x,it
[8]: A=array([[8,1,2,1],[1,5,-1,-1],[1,-4,6,1],[1,-2,1,5]],float)
V=array([-1,3,2,1],float)
x1,it=gauss_seidel(A,V,1e-6)
x2,AB=gaussian_elim(A,V)
print(x1,x2,sep=", ")
print("El número de itracciones del método de Gauss-Seidel es: ",it)
27
!
i −1 N
ω
xik+1 = (1 − ω ) xik + vi − ∑ aij x kj +1 − ∑ aij x kj ,
aii j =1 j = i +1
def gauss_seidel_rel(A,v,w,eps):
while err>eps:
x=(v-dot(U,x0))
# Sustitución hacía adelante
for m in range(N):
for i in range(m):
x[m]-= DL[m,i]*x[i]
x[m]=(1-w)*x0[m]+w/DL[m,m]*x[m]
err=max(abs(x-x0))
x0=copy(x)
it+=1
return x,it
[10]: A=array([[8,1,2,1],[1,5,-1,-1],[1,-4,6,1],[1,-2,1,5]],float)
V=array([-1,3,2,1],float)
w=1.1
x1,it=gauss_seidel_rel(A,V,w,1e-6)
x2,AB=gaussian_elim(A,V)
print(x1,x2,sep=", ")
print("El número de itracciones del método de la sobrerelajación sucesiva es:␣
,→",it)
28
[-0.57409704 1.02366121 1.02490661 0.51930259], [-0.57409714 1.02366127
1.0249066 0.51930262]
El número de itracciones del método de la sobrerelajación sucesiva es: 9
2. Autovalores y autovectores
Los problemas de autovalores son fundamentales en muchos campos de la física.
En la mayoría de los casos físicos, involucran matrices reales simétricas o complejas hermí-
ticas.
En esos casos la matriz es diagonalizable, y el problema es equivalente a encontrar el sistema
de coordenadas para el que la matriz es diagonal.
En particular, para una matriz simétrica de dimensión N × N el problema de autovalores:
A · vi = λi vi , i = 1, · · · , N
A · V = D · V,
con D una matriz diagonal cuyos valores son los autovalores λi y V una matriz ortogonal,
es decir que satisface,
V T · V = V · V T = I,
2.1. Descomposición QR
El método más común usado para calcular los autovalores de una matriz es la descomposi-
ción QR.
Es parecida a la factorización LU, pero en este caso la matriz A se descompone como
A = Q · R,
| | ··· |
A = a1 a2 · · · an
| | ··· |
29
que podemos usar para construir los vectores ui y qi con i = 1, · · · , N definidos por
u1
u1 = a1 , q1 = ,
| u1 |
u2
u2 = a2 − ( q1 · a2 ) q1 , q2 = ,
| u2 |
u3
u3 = a3 − ( q1 · a3 ) q1 − ( q2 · a3 ) q2 , q3 = ,
| u3 |
(8)
y de forma general
i −1
ui
ui = ai − ∑ a j · q j q j ,
qi = ,
j =1
| ui |
Los vectores qi forma una base de vectores ortonormales, que permiten escribir:
| | ··· |
| | ··· | | u1 | ( q1 · a2 ) · · · ( q1 · a n )
A= a1 a2 · · · an = q1 q2 · · · qn 0
· | u2 | ··· ( q2 · a n )
= Q·R
| | ··· | | | ··· | .
.. .
.. .. ..
. .
1 4 8 4
4 2 3 7
A=
8
,
3 6 9
4 7 9 2
def QR_fact(A):
N=len(A)
U = zeros([N,N],float)
Q = zeros([N,N],float)
30
R = zeros([N,N],float)
for m in range(N):
U[:,m] = A[:,m] # Creamos los vectores de U
for i in range(m):
R[i,m] = dot(Q[:,i],A[:,m]) # los vamos calculando en cada␣
,→iteracción
U[:,m] -= R[i,m]*Q[:,i]
R[m,m] = norm(U[:,m])
Q[:,m] = U[:,m]/R[m,m]
return Q,R
[3]: A=array([[1,4,8,4],
[4,2,3,7],
[8,3,6,9],
[4,7,9,2]],float)
Q,R=QR_fact(A)
print(Q)
print()
print(R)
print()
print(dot(Q,R)-A)
A = Q1 · R1 ,
31
Q1T · A · Q1 = Q1T · Q1 · R1 · Q1 = R1 · Q1 ,
A1 · v1 = Q1T · A · Q1 · v1 = λ1 v1 ⇒ A · ( Q1 · v1 ) = λ1 ( Q1 · v1 ) ,
A1 = Q1T · A · Q1 = Q2 · R2 ,
A1 = Q1T · A · Q1 ,
A2 = Q2T · Q1T · A · Q1 · Q2 ,
A3 = Q3T · Q2T · Q1T · A · Q1 · Q2 · Q3 ,
.. ..
. .,
An = QnT · · · Q1T · A · ( Q1 · · · Qn ) ,
(9)
Una matriz ortogonal no es más que un cambio de coordenadas, es decir, una rotación.
Por ejemplo, en dos dimensiones, N=2:
cos α − sin α
Q= ,
sin α cos α
32
[6]: <[Link] object>
k
V = ( Q1 · · · Q n ) = ∏ Qi ,
i =1
obtenemos que:
V T · A · V = D ⇒ A · V = D · V.
1 4 8 4
4 2 3 7
A=
8
,
3 6 9
4 7 9 2
33
Escribir un programa que utilice la factorización QR para obtener los autovalores de A asegurando
que los elementos de fuera de la diagonal son menores de 10−6 .
[4]: A=array([[1,4,8,4],
[4,2,3,7],
[8,3,6,9],
[4,7,9,2]],float)
Q,R=QR_fact(A)
print(Q)
print()
print(R)
print()
print(dot(Q,R)-A)
N=len(A)
V = identity(N,float) # Empezamos con la identidad
delta = 1.0
while delta > eps:
# Hacemos un paso del algoritmo QR
Q,R = QR_fact(A)
A = dot(R,Q)
V = dot(V,Q)
Ac = copy(A)
for i in range(N):
34
Ac[i,i]=0.0
delta = max(absolute(Ac))
return A,V
D,V=QR_diag(A,1e-12)
print(D)
print()
print(V)
print()
print("Nuestros autovalores son: ",diag(D))
for i in range(len(A)):
print(dot(A,V[:,i])- diag(D)[i]*V[:,i])
35
2.3.3. Ejercicio 5.2: Pozo de potencial asimétrico en Mecánica Cuántica
La Mecánica Cuántica puede formularse como un problema matricial que puede resolverse en un
ordenador usando los métodos del álgebra lineal.
Estudiemos por ejemplo una partícula de masa m en un potencial unidimensional de de longitud
L descrito por una función V ( x ).
En general estos problemas no pueden resolverse analíticamente y tienen que ser analizados en
un ordenador. Un autoestado de energía E satisface la ecuación de Schrödinger independiente del
tiempo:
Ĥψ( x ) = E ψ( x ),
36
h̄2 d2
Ĥ = − + V ( x ).
2M dx2
Asumamos que las paredes del potencial tienen una altura infinita, que nos permite definir que la
función de onda se anula para x = 0 y L.
En ese caso la función de onda puede escribirse como una series de Fourier:
∞
πnx
ψ( x ) = ∑ ψn sin L
,
n =1
ZL
πmx πnx L/2 si m = n
sin sin dx =
L L 0 de otra forma.
0
∞ ZL
πmx πnx 1
∑ ψn sin
L
Ĥ sin
L
dx = LE ψm .
2
n =1 0
ZL
2 πmx πnx
Hmn = sin Ĥ sin
L L L
0
ZL
" #
2 πmx h̄2 d2 πnx
= sin − 2
+ V ( x ) sin ,
L L 2M dx L
0
H · ψ = Eψ
37
3. Asumiendo ahora que V ( x ) = ax/L, resolver la integral analíticamente,que permite encon-
trar una expresión para el elemento de matriz Hmn . Mostrar que la matriz es real y simétrica.
Tener en cuenta que:
ZL 0 si m 6= n y ambos son pares o impares
2L 2
πmx πnx
mn
x sin sin dx = − 2 si m 6= n y uno es par y otro impar
L L π ( m2 − n2 )
0
2
L /4 si m = n
4. Escribir un programa que calcule Hmn para cualquier valor de m y n para un electrón en un
pozo de anchura L = 5 Å y a = 10 eV.
(Ayuda me = 9,1094 × 10−31 Kg y e = 1,6022 × 10−19 C).
5. La matriz H es infinitamente grande por lo que no es posible calcular sus autovalores. Sin
embargo, se puede obtener una solución aproximada muy buena si sólo consideramos los
primeros autovalores.
Crear una matriz 10 × 10 de los elementos de matriz hasta m, n = 10 y calcular sus autova-
lores y auto vectores.
6. Hacerlo ahora una matriz 100 × 100 y comparar los resultados.
7. Representar la densidad de probabilidad |ψ( x )|2 para función de onda ψ( x ) normalizada,
para el estado fundamental y los dos primeros estados excitados.
[ ]:
3. Ecuaciones no lineales
Por ahora sólo hemos aprendido a resolver sistemas de ecuaciones lineales.
Pero muchas ecuaciones que aparecen en Física son no-lineales.
Las ecuaciones no lineales son mucho más complicadas de resolver.
En particular, resolver una única ecuación no lineal puede ser ya complicado, por lo que
resolver varias a la vez aún más dífícil.
En este apartado veremos algunas técnicas para enfrentarnos a estos problemas.
Empezaremos por el caso de una única ecuación no-lineal.
x = f ( x ),
38
x1 = f ( x0 ),
xk+1 − xk = f ( xk ) − xk = 0.
Lo relevante es por tanto estudiar bajo que condiciones ese proceso iterativo converge a la
solución exacta.
Para ello supongamos que tenemos una estimación de la solución xi y definamos la solución
exacta como x̄.
Expandiendo en serie de Taylor en torno a la solución, se tiene:
xi+1 = f ( xi ) = f ( x̄ ) + ( xi − x̄ ) f 0 ( x̄ ) + · · · = x̄ + ( xi − x̄ ) f 0 ( x̄ ) + · · · ,
por tanto, la diferencia entre nuestra siguiente estimación y la solución exacta es:
xi+1 − x̄ = ( xi − x̄ ) f 0 ( x̄ ) + · · · ,
| f 0 ( x̄ ) | < 1.
x = 2 − e− x ,
def f(x):
return 2-exp(-x)
39
it+=1
x0=x1
print(it,x1)
1 1.6321205588285577
2 1.8044854658474119
3 1.8354408939220457
4 1.8404568553435368
5 1.841255113911434
6 1.8413817828128696
7 1.8414018735357267
8 1.8414050598547234
9 1.8414055651879888
print(derx0,exp(-x0),sep=", ")
0.1585943546711377, 0.15859435466898786
| f 0 ( x̄ )| > 1,
x = f ( x ) ⇒ x = f −1 ( x ),
0 1
xi+1 = f −1 ( xi ) = f −1 ( x̄ ) + ( xi − x̄ ) f −1 ( x̄ ) + · · · = x̄ + ( xi − x̄ ) +··· ,
f 0 ( x̄ )
| f 0 ( x̄ ) | > 1.
40
Ejemplo 5.15: aplicando el método del punto fijo por segunda vez aplicar el método del punto
fijo para encontrar la solución a la ecuación
2
x = e1− x .
La ecuación no tiene solución analítica. Sin embargo se ve trivialmente que x = 1 es una solución.
La derivada de la función en ese punto es:
2
f 0 (x) x =1
= − 2 x e1 − x = −2,
x =1
y por tanto, la aplicación directa del método del punto fijo no va a funcionar. Comprobémoslo con
las 10 primeras iteraciones:
1, 2.718281828459045
2, 0.0016798410570681988
3, 2.71827415784286
4, 0.001679911110814363
5, 2.718274157203078
6, 0.00167991111665744
7, 2.7182741572030253
8, 0.0016799111166579221
9, 2.7182741572030253
10, 0.0016799111166579221
La estimación va oscilando continuamente sin obtener ningún patrón de convergencia.
Haciendo uso de que la inversa de la función existe, podemos reescribir el problema como:
p
x= 1 − log x,
def f(x):
return sqrt(1-log(x))
41
eps=1e-6 # definimos la
it=0
err=1.0
x0=0.5
while err>eps:
x1=f(x0)
err=abs(x1-x0)
it+=1
x0=x1
print(it,x1)
1 1.3012098910475378
2 0.8583154914892762
3 1.0736775779454883
4 0.9637999044091371
5 1.0182689104343374
6 0.990906635925747
7 1.004557096969838
8 0.997724037576543
9 1.0011386299421705
10 0.9994308469350205
11 1.000284617043603
12 0.9998577016016549
13 1.000071151730577
14 0.9999644247674951
15 1.0000177877744567
16 0.9999911061523217
17 1.0000044469337268
18 0.9999977765356085
19 1.0000011117328136
20 0.9999994441337476
21 1.000000277933165
42
Ejemplo 5.16: aplicando el método del punto fijo por tercera vez dada la ecuación:
x = x2 + sin 2x,
cuya solución es x = 0, explicar si es resoluble por medio del método de relajación/punto fijo.
En caso negativo, intentar reescribir la ecuación de forma que el método converja.
La derivada de la función en x=0 es | f 0 ( x )| = 2, por lo que el método de relajación no funcionará.
Además, la función f ( x ) = x2 + sin 2x no es invertible.
Sin embargo, reescribiendola como:
1
sin−1 x − x2 ,
x = g( x ) =
2
se puede comprobar que en ese caso: | g0 ( x )| = 1/2 por lo el método del punto fijo en este caso si
va a converger hacía la solución.
def f(x):
return arcsin(x-x*x)/2
eps=1e-6 # definimos la
it=0
err=1.0
x0=1e-4
while err>eps:
x1=f(x0)
err=abs(x1-x0)
it+=1
x0=x1
print(it,x1)
1 4.999500008330834e-05
2 2.4996250302049482e-05
3 1.249781274606156e-05
4 6.248828275531731e-06
5 3.12439461385879e-06
6 1.5621924260110852e-06
7 7.810949927832724e-07
3.1.4. Convergencia y estimación del error del método del punto fijo/relajación
Una vez hemos visto las condiciones por las cuales el método del punto fijo converge, el
paso siguiente es saber como de rápido lo hace.
Dada una iteración i la diferencia con la solución exacta es
43
| xi+1 − x̄ | = | xi − x̄ | | f 0 ( x̄ ) | + · · · = | xi−1 − x̄ | | f 0 ( x̄ ) |2 + · · · = · · · = | x0 − x̄ | | f 0 ( x̄ ) |i+1 + · · · ,
0 ( x̄ )| 0
= | x0 − x̄ | e(i+1) log | f + · · · = | x0 − x̄ | e−(i+1) log(1/| f (x̄)|) + · · ·
(10)
x̄ = xi + ei = xi+1 + ei+1 ,
ei + 1
ei = ,
f 0 ( x̄ )
ei + 1 x i − x i +1
x i + 1 + ei + 1 = x i + 0
⇒ ei + 1 = ,
f ( x̄ ) 1 − 1/ f 0 ( x̄ )
Sin embargo, en general no conocemos la solución exacta, que es la que estamos buscando.
Aproximando que nuestra estimación k-esima no esta lejos de la solución, podemos desarro-
llar f 0 ( x̄ ) en serie de Taylor
f 0 ( x̄ ) = f 0 ( xi ) − ( x̄ − xi ) f 00 ( xi ) + · · · ' f 0 ( xi ),
x i − x i +1
ei + 1 ' .
1 − 1/ f 0 ( xi )
Por tanto sólo tenemos que repetir la iteración hasta que ei+1 < e siendo e nuestra tolerancia,
sin necesidad de calcular la siguiente iteración i + 2.
Sin embargo, en el caso de no conocer la forma funcional de f ( x ) tendremos que estimar su
derivada numéricamente:
f ( x i ) − f ( x i −1 ) x − xi
f 0 ( xi ) ' = i +1 ,
x i − x i −1 x i − x i −1
44
( x i − x i +1 )2
ei + 1 ' ,
2xi − xi+1 − xi−1
x i +1 = f ( x i )
xi+1 = xi + (1 + ω ) ∆xi+1 = xi + (1 + ω ) ( f ( xi ) − xi ) = (1 + ω ) f ( xi ) − ω xi .
Si el parámetro ω > 0 la iteración cambia por un factor ω∆xi+1 más de lo que hace el método
de relajación normal.
Para que el método funcione ω tiene que escogerse correctamente.
Lamentáblemebte no hay una teoría general que permite obtener el valor óptimo de ω, que
normalmente se obtiene por prueba y error.
45
Ejercicio 5.4: aplicando el método del punto fijo sobrerelajado
1. Obtener la ecuación que da el error de una estimación dada usando el método de sobrerela-
jación.
2. Modificar el programa del Ejercicio 5.3 para que calcule el número de iteracciones necesarias
para llegar a la solución. Calcularlas para c=2.
3. Modificar de nuevo el programa para buscar la solución de la ecuación del Ejercicio 5.3 con
c=2 usando el método de la sobrerelajación. Empezar con un valor de ω = 0,5 y variarlo
hasta encontrar el valor que minimiza el número de iteracciones.
4. ¿Hay alguna situación en la que el método de la sobrerelajación pueda funcionar para ω <
0?.
[ ]:
3.1.7. Método del punto fijo o relajación con más de una variable
El método del punto fijo o relajación se puede extender fácilmente para el estudio de sistemas
de ecuaciones no lineales en varias variables.
Dadas N ecuaciones con N incógnitas:
x1 = f 1 ( x1 , · · · , x N ),
x2 = f 2 ( x1 , · · · , x N ),
.. ..
. .
x N = f N ( x1 , · · · , x N ),
(11)
(0)
partiendo de una estimación inicial para cada una de las variables, xi con i = 1, · · · , N,
aplicamos las ecuaciones iterativamente hasta encontrar una solución.
Como en una dimensión, la convergencia no esta garantizada.
En este caso se puede demostrar que el sistema convergerá si todos los autovalores λi de la
matriz jacobiana J, aquella cuyos elementos de matriz son:
d f k ( x1 , · · · , x N )
Jkl = ,
dxl
46
Ejercicio 5.5: El proceso de la glucólisis La glucólisis es el proceso bioquímico que permite oxi-
dar la glucosa para extraer de ella energía y puede ser modelado por las ecuaciones:
dx dy
= − x + ay + x2 y, = b − ay − x2 y,
dt dt
0 = − x + ay + x2 y, 0 = b − ay − x2 y.
1. Obtener los valores de los puntos estacionarios.
2. Probar que en los puntos estacionarios, las ecuaciones de la glucólisis se pueden escribir
como:
b
x = y ( a + x 2 ), y= .
a + x2
[ ]:
f ( x ) = 0,
47
3.2.1. Algoritmo para el método de la bisección
1. Definimos el intervalo en el que queremos encontrar una solución (x1 , x2 ).
Comprobamos que los valores de la función en esos puntos, f ( x1 ) y f ( x2 ) tienen signos
diferentes.
En ese caso, sí la función es continua, debe haber como mínimo un punto en el que función
se anula (teorema de Bolzano).
Se dice por tanto que el intervalo [ x1 , x2 ] contiene la raíz.
2. Calculamos el punto intermedio del intervalo, x 0 = 1
2 ( x1 + x2 ), y evaluamos la función
f ( x 0 ).
3. Si f ( x 0 ) tiene el mismo signo de f ( x1 ), hacemos la sustitución x1 = x 0 . En caso contrario
hacemos x2 = x 0 .
4. Si | x1 − x2 | > e, con e la precisión objetivo de nuestra solución, volvemos al paso 2.
En caso contrario nuestra estimación de la solución es el nuevo punto medio: x 0 =
1
2 ( x1 + x2 ).
48
3.2.2. Convergencia del método de la bisección
Al igual que con el método del punto fijo la precisión mejora exponencialmente.
La distancia entre dos estimaciones se divide por dos en cada iteración.
Por tanto, llamando e0 = | x1 − x2 | al error asociado a la estimación inicial, al cabo de n
iteraciones:
e0
en = = e0 e−n log 2 .
2n
Esto nos permite calcular el número de iteraciones necesarias N para llegar a una precisión
objetivo e:
e0
N = log2 .
e
Como el logaritmo es una función que crece muy lentamente, esto nos asegura que con un
número de pasos razonable podremos encontrar la solución con una determinada precisión.
Por ejemplo, sí e0 = | x1 − x2 | = 1010 y nuestra precisión objetivo e = 10−10 el número de
iteraciones necesarias será:
[20]: from math import log
log(10**20,2)
[20]: 66.43856189774725
49
Igualmente, es muy posible que no se tenga una estimación inicial del intervalo en el que
debe encontrarse la raíz.
Cualquier par de puntos para los que la función tenga diferente signo valdrán, pero encon-
trarlos puede no ser fácil.
Reglas generales que facilitan encontrar el intervalo inicial son:
• Si se tiene información sobre la función que permite encontrar donde puede estar la
raíz, tenerla en cuenta.
Por ejemplo, si se conoce el signo de la función por consideraciones físicas en un deter-
minado intervalo.
• Si se busca una solución en torno a un punto eso ayuda.
Tomamos entonces un entorno alrededor del punto y vamos aumentando el tamaño
hasta que contenga una raíz.
De la misma forma, el método no permite encontrar soluciones de raíces múltiples pares.
Estos problemas son equivalentes a encontrar el mínimo de una función.
50
Finalmente, es un método que no se puede generalizar a funciones de más de una variable.
f ( x ) = ex − 2,
def f(x):
return exp(x)-2
x=linspace(-2,2,100)
fig,ax=subplots(1,1,figsize=(12, 4)) # subplots(#filas,#columas)
51
# nos permite crear varias gráficas en una␣
,→ sólo llamada.
# y cambiar facilmente sus propiedades
[Link](x,f(x),lw=1.5)
[Link](0,ls=':',color="k")
ax.set_xticks([-2, -1, 0, 1, 2])
ax.set_xlabel(r'$x$', fontsize=18)
ax.set_ylabel(r'$f(x) = e^x - 2$', fontsize=18)
show()
fig2,ax2=subplots(1,1,figsize=(12, 4))
[Link](x,f(x),lw=1.5)
# Lo añadimos a la figura.
[Link](a,fa, 'ko')
[Link](b,fb, 'ko')
[Link](a,fa + 0.5, r"$a$", ha='center', fontsize=18)
[Link](b,fb + 0.5, r"$b$", ha='center', fontsize=18)
show()
52
[13]: from numpy import sign
fig3,ax3=subplots(1,1,figsize=(12, 4))
[Link](x,f(x),lw=1.5)
[Link](a,fa, 'ko')
[Link](b,fb, 'ko')
[Link](a,fa + 0.5, r"$a$", ha='center', fontsize=18)
[Link](b,fb + 0.5, r"$b$", ha='center', fontsize=18)
it=0
while b-a>eps:
m=a+(b-a)/2
fm=f(m)
[Link](m,fm,'ko')
[Link](m,fm-0.5, r"$m_%d$" %it,ha='center')
it += 1
if sign(fa)==sign(fm):
a,fa=m,fm
else:
b,fb= m,fm
print(it)
[Link](m,fm,'r*',markersize=10)
53
[Link]("Raíz aproximada en %.3f" % m,fontsize=14, family="serif",
xy=(m, fm), xycoords='data',
xytext=(-150, +50), textcoords='offset points',
arrowprops=dict(arrowstyle="->", connectionstyle="arc3, rad=-.5"))
ax3.set_title("Método de la Bisección")
show()
22
2π h c2 λ−5
I (λ) = ,
ehc/λk B T − 1
hc
5e−hc/λk B T + − 5 = 0.
λk B T
5e− x + x − 5 = 0,
54
b
λ= ,
T
siendo
hc
b= ,
kB x
[ ]:
f ( x ) = 0,
es decir, en buscar las raíces de la función, las cuales se estiman extrapolando la pendiente
de la función en un punto dado.
[34]: display(Image("[Link]",width=600,height=600))
55
Dada una estimación inicial x la nueva estimación viene dada por:
f (x)
x 0 = x − ∆x = x − ,
f 0 (x)
1
f ( x̄ ) = f ( x ) + ( x̄ − x ) f 0 ( x ) + ( x̄ − x )2 f 00 ( x ) + · · · = 0.
2
56
Despejando, se obtiene:
f (x) 00 00
1 2 f (x) 0 1 2 f (x)
x̄ = x − − ( x̄ − x ) + · · · = x − ( x̄ − x ) +···
f 0 (x) 2 f 0 (x) 2 f 0 (x)
−1 f 00 ( x )
e = x̄ − x 0 = ( x̄ − x )2 0 .
2 f (x)
−1 f 00 ( x 0 ) 1 f 00 ( x 0 ) 2
e0 = x̄ − x 00 = ( x̄ − x 0 )2 0 0 = e ,
2 f (x ) 2 f 0 (x0 )
2 N
2 k
eN ' e0 ,
k 2
57
3.3.2. Desventajas del método de Newton-Raphson.
Necesitamos conocer la derivada de f ( x ).
El método no siempre converge:
por ejemplo si f 0 ( x ) es muy pequeña, el método iterativo hará que el error de cada iteración
sea mayor que en la anterior.
Puede ocurrir que la pendiente de la función apunte en el sentido contrario de la raíz.
[35]: display(Image("[Link]",width=600,height=600))
f ( x ) = ex − 2,
58
usando el método de Newton-Raphson con una precisión mayor de 10−6 .
def f(x):
return exp(x)-2
# Definimos su derivada
def fp(x):
return exp(x)
x=linspace(-2,2,100)
fig,ax=subplots(1,1,figsize=(12, 4)) # subplots(#filas,#columas)
# nos permite crear varias gráficas en una␣
,→sólo llamada.
# Aplicamos el método de newton hasta que nuestro error sea menor que la␣
,→precisión
while f(x1)>eps:
x2 =x1-f(x1)/fp(x1)
[Link](x1,f(x1),'ko')
[Link](x2,0,'ko')
[Link]([x1,x1],[0,f(x1)],color='k',ls=':')
[Link](x1,-.5, r'$x_%d$' %it,ha='center')
[Link]([x1,x2], [f(x1), 0], 'k-')
x1=x2
it+=1
print("Hemos necesitado",it,"iteracciones.")
[Link](x1, f(x1), 'r*', markersize=15)
59
[Link]("Raíz aproximada en %.3f" %x1,fontsize=14, family="serif",␣
,→xy=(x1,f(x1)), xycoords='data',
ax.set_title("Método de Newton-Raphson")
fig.tight_layout()
show()
x = arctanh u =⇒ u = tanh x.
[ ]:
60
3.3.6. Método de la secante
Una de las limitaciones del método de Newton-Raphson es que debemos conocer la derivada
de f ( x ).
Si no es el caso, aún la podemos estimar numéricamente usando las técnicas estudiadas en
el Tema 4,
que es lo que llamamos el método de la secante.
Para calcularla, necesitamos como mínimo puntos x1 y x2 que a diferencia del método de la
bisección, no tienen que contener a la raíz.
Con ellos calculamos la aproximación de la derivada:
f ( x2 ) − f ( x1 )
f 0 ( x2 ) = .
x2 − x1
( x2 − x1 )
x3 = x2 − f ( x2 ) ,
f ( x2 ) − f ( x1 )
f 1 ( x1 , · · · , x N ) = 0 ,
f 2 ( x1 , · · · , x N ) = 0 ,
.. ..
. .
f N ( x1 , · · · , x N ) = 0 ,
(12)
∂ fi
f i ( x̄1 , · · · , x̄ N ) = f i ( x1 , · · · , x N ) + ∑ x̄ j − x j +··· ,
j
∂x j
F ( x̄ ) = F ( x ) + J · ( X̄ − X ) + · · · ,
61
siendo J la matriz jacobiana del sistema de ecuaciones, es decir la matriz N × N con elemen-
∂f
tos Jij = ∂xij .
J · ( X − X̄ ) = J · ∆X = F ( x ),
X 0 = X − ∆X.
En el caso de que la matriz Jacobiana no sea conocida, se puede estimar por medio del
método de las derivadas finitas, que generaliza por tanto el método de la secante para más
de una variable.
Ejemplo 5.19: representación gráfica del método de Newton-Raphson en varias variables. Re-
solver el sistema de ecuaciones:
y − x3 − 2 x2 + 1 = 0,
y + x2 − 1 = 0,
(13)
def f(x):
return [x[1] - x[0]**3 - 2 * x[0]**2 + 1, x[1] + x[0]**2 - 1]
def fJ(x):
return [[- 3*x[0]**2 - 4*x[0],1],[ 2*x[0],1]]
x=linspace(-3, 2, 5000)
y1=x**3+2*x**2-1
y2=-x**2+1
62
fig,ax=subplots(figsize=(8,4))
[Link](x,y1,'b',lw=1.5, label=r'$y = x^3 + 2x^2 - 1$')
[Link](x,y2,'g',lw=1.5, label=r'$y = -x^2 + 1$')
[Link](loc=0)
axhline(0,ls=':',color="k")
show()
fig,ax=subplots(figsize=(8,4))
[Link](x,y1,'b',lw=1.5, label=r'$y = x^3 + 2x^2 - 1$')
[Link](x,y2,'g',lw=1.5, label=r'$y = -x^2 + 1$')
axhline(0,ls=':',color="k")
for i in x0:
[Link](i[0],i[1],'ko',markersize=10)
show()
63
[3]: # Aplicamos el método de Newton Rapshon
from numpy import copy
from [Link] import solve
eps=1e-6
x1=copy(x0)
it=0
for i in x1:
err=1
while err>eps:
dx=solve(fJ(i),f(i))
i-=dx
err=abs(max(dx))
x1[it]=i
it+=1
[4]: # Lo representamos
fig,ax=subplots(figsize=(8,4))
[Link](x,y1,'b',lw=1.5, label=r'$y = x^3 + 2x^2 - 1$')
[Link](x,y2,'g',lw=1.5, label=r'$y = -x^2 + 1$')
axhline(0,ls=':',color="k")
for k in range(3):
[Link](x1[k,0],x1[k,1],'r*', markersize=15)
[Link](x0[k,0],x0[k,1], 'ko')
[Link]("", xy=(x1[k,0],x1[k,1]), xytext=(x0[k,0],x0[k,1]),
64
arrowprops=dict(arrowstyle="->", linewidth=2.5))
[Link](loc=0)
ax.set_xlabel(r'$x$',fontsize=18)
fig.tight_layout()
show()
sol1=[Link](f,x0[0])
sol2=[Link](f,x0[1])
sol3=[Link](f,x0[2])
print(sol1,x1[0])
print(sol2,x1[1])
print(sol3,x1[2])
65
[9]: fig,ax=subplots(figsize=(8, 4))
[Link](x, y1, 'k', lw=1.5, label=r'$y = x^3 + 2x^2 - 1$')
[Link](x, y2, 'k', lw=1.5, label=r'$y = -x^2 + 1$')
x00=[m, n]
sol=[Link](f,x00)
ax.set_xlabel(r'$x$',fontsize=18)
fig.tight_layout()
show()
Ejercicio 5.9: sistema de circuitos no lineales Mientras que las resistencias introducen un efecto
lineal en la intensidad de corriente respecto a la diferencia de potencial (Ley de Ohm),
I = ∆V/R,
66
I = I0 e∆V/VT − 1 ,
siendo V la diferencia de voltaje entre los extremos del diodo e I0 , V0 parámetros dependientes de
su composición.
Dado el siguiente circuito:
67
V+ = 5 V, R1 = 1 kΩ, R2 = 4 kΩ, R3 = 3 kΩ, R4 = 2 kΩ, I0 = 3 nA, VT = 0,005 V.
[ ]:
68
4.1. Estrategia general
Si es posible calcular la derivada:
• Buscar los puntos estacionarios en los que se anulen la derivada o las derivadas parcia-
les.
Si estamos buscando el mínimo de una función: f ( x1 , x2 , · · · ) resolvemos el sistema:
∂ f ( x1 , x2 · · · )
= 0, j = 1, 2, · · ·
∂x j
69
4.2. Método de la razón áurea
Es análoga al método de la bisección pero para la búsqueda de mínimos.
Sólo sirve para funciones de una variable: buscamos los mínimos de f ( x ).
Al igual que el método de la bisección, requiere partir de dos valores de la variable x que
contengan el mínimo.
La situación que consideramos es la siguiente:
[3]: display(Image("[Link]",width=600,height=600))
70
4. El problema reside en optimizar la posición de los puntos x2 y x3 .
Optimizando la posición de los puntos interiores
1. Como no sabemos en que lado del intervalo [ x1 , x4 ] se encuentra el mínimo, x2 y x3 deben
estar distribuidos simétricamente:
x2 − x1 = x4 − x3 .
2. Si x2 y x3 se encuentran muy cerca del centro del intervalo [ x1 , x4 ], uno de los intervalos de
la siguiente iteración, para el segmento [ x1 , x3 ] o [ x2 , x4 ] será mucho más grande que el otro.
Definimos el cociente entre los intervalos en dos iteraciones consecutivas:
x4 − x1 x2 − x1 + x3 − x1 x2 − x1
z= = = + 1, si f ( x2 ) < f ( x3 ),
x3 − x1 x3 − x1 x3 − x1
x4 − x1 x − x2 + x4 − x3 x − x3
z= = 4 = 4 + 1, si f ( x2 ) > f ( x3 ),
x4 − x2 x4 − x2 x4 − x2
(14)
x3 − x1
z0 = , si f ( x2 ) < f ( x3 ),
x2 − x1
x4 − x2
z0 = , si f ( x2 ) > f ( x3 ),
x4 − x3
(15)
Si queremos que el algoritmo sea igual de eficiente en dos iteraciones sucesivas entonces,
debemos imponer que z = z0 que implica que
z2 − z − 1 = 0,
como z>1 sólo podemos coger la solución positiva que implica que:
√
1+ 5
z= = 1,618...
2
x4 − x1 x4 − x1
x2 = x4 − , x3 = x1 +
z z
71
4.2.1. Algoritmo del método de la razón áurea
1. Escogemos una precisión para la obtención del mínimo.
2. Escogemos dos puntos en los extremos del intervalo en el que vamos a buscar el mínimo x1
y x4 .
Calculamos los puntos del interior x2 y x3 con la regla da la razón aúrea.
Evaluamos f ( x ) en los cuatro puntos y comprobamos que al menos uno de los valores
de la función en x2 o x3 es menor que en x1 y x4 .
3. Si f ( x2 ) < f ( x3 ) entonces el mínimo esta entre x1 y x3 , en este caso x3 se transforma en el
nuevo x4 , x2 se transforma en el nuevo x3 y habrá un nuevo x2 , obtenido por la regla de la
razón aúrea. Evaluamos f ( x ) en este nuevo punto.
4. En caso contrario, el mínimo esta entre x2 y x4 , entonces x2 se convierte en el nuevo x1 , x3
se convierte en el nuevo x2 , y habrá un nuevo x3 elegido con la regla de la razón aúrea.
Evaluamos f ( x ) en este nuevo punto.
5. Si x4 − x1 es mayor que la precisión requerida, repetimos desde el paso 3.
En caso contrario, calculamos 21 ( x2 + x3 ) y esta será nuestra estimación final de la posición
del mínimo.
72
[1]: # 1- Constantes del problema
def f(r):
return (sigma/r)**6-exp(-r/sigma)
x = linspace(0.1,10,1000)
ylim(-0.2,0.1)
plot(x,f(x))
show()
x1=sigma/10
x4=sigma*10
73
x2=x4-(x4-x1)/z
x3=x1+(x4-x1)/z
f1=f(x1)
f2=f(x2)
f3=f(x3)
f4=f(x4)
while x4-x1>eps:
if f2<f3:
x4,f4=x3,f3
x3,f3=x2,f2
x2=x4-(x4-x1)/z
f2=f(x2)
else:
x1,f1=x2,f2
x2,f2=x3,f3
x3=x1+(x4-x1)/z
f3=f(x3)
xmin=(x1+x4)/2
print("El mínimo cae en",0.5*(x1+x4),"nm")
plot(x,f(x))
plot(xmin,f(xmin),"ko")
ylim(-0.2,0.1)
show()
74
4.2.4. Ejercicio 5.10: la temperatura de una bombilla
Tradicionalmente, una bombilla esta formada por un filamento de tungsteno, que se calienta cuan-
do la corriente eléctrica pasa por él, emitiendo radiación térmica. Esencialmente toda la energía
consumida es radiada electromagnéticamente, pero una parte de esa radiación no es emitida en el
espectro visible.
Definamos la eficiencia de una bombilla como la energía radiada en el visible entre la total. Asu-
miendo que un filamento de tungsteno cumple la ley de Planck, la potencia radiada por unidad
de longitud de onda viene dada por:
λ −5
I (λ) = 2πAhc2 ,
ehc/λk B T − 1
siendo A la superficie del área del filamento de tungsteno, h la constante de Planck, c la velocidad
de la luz, k B la constante de Boltzmann.
Teniendo en cuenta que radiación visible se encuentra entre las longitudes de onda λ1 = 390 nm
y λ2 = 750 nm.
hc
1. Llamando x = x (λ) = , y xi = x (λi ) con i = 1, 2, probar que la eficiencia de una
λk B T
bombilla de tungsteno η viene dada por la integral:
R x2
x
x3 /(ex − 1) dx 15
Z x2
x3
η = R ∞1 = dx,
0
x3 /(ex − 1) dx π4 x1 (e x − 1)
75
donde en el último paso hemos hecho uso de que la integral del denominador se conoce
analíticamente.
2. Escribir un programa que tome la temperatura como argumento y que calcule el valor de η
para dicho valor.
Como la integral no se puede resolver analíticamente, usar el método más conveniente para
integrarla numéricamente.
Representar la eficiencia de la bombilla para temperaturas entre 300 K y 10000 K.
Comprobar que hay una temperatura intermedia para la que la eficiencia es máxima.
3. Calcular la temperatura que corresponde al máximo de la eficiencia con una precisión de 1
K usando la razón áurea.
4. ¿Tiene sentido practico calentar el tungsteno a la temperatura del máximo?.
[ ]:
f 0 ( x ) = 0,
f 0 (x)
x0 = x − ,
f 00 ( x )
Si conocemos la función y sus derivadas, el método nos permite encontrar los máximos y
mínimos de una función de forma rápida y fiable.
El método de Gauss-Newton converge de forma cuadrática y puede generalizarse a varias
variables.
Sin embargo es bastante común que la primera y/o la segunda derivada no sean conocidas.
En ese caso estás se pueden aproximar usando los métodos de la diferencias finitas del Tema
3.
Da lugar a un método de la secante para un problema de minimización.
76
4.4. El método del gradiente descendente
El método del gradiente descendente es una modificación del método de Gauss-Newton
para el caso en que la segunda derivada no se puede calcular ni aproximar correctamente.
En ese caso, se aproxima por una constante γ que debe tener el orden de magnitud correcto
de forma que:
x 0 = x − γ f 0 ( x ).
El valor de γ no tiene que estar determinado muy precisamente, es suficiente con que el
orden de magnitud sea correcto.
Si γ tiene signo positivo el método le sustraerá el valor de la derivada γ veces a nuestra
estimación x, y el método convergerá hacía un mínimo.
Si γ tiene signo negativo, el método le añadirá dicho valor, y convergerá a un máximo.
Si γ es grande podemos converger más rápidamente, pero si lo es demasiado pasaremos por
encima del mínimo y el método fallará.
El valor de γ tiene que ser optimizado para maximizar la convergencia sin saltarnos en
ningún momento el máximo.
Para ello, el método más rápido es probar con varios valores hasta encontrar el valor más
óptimo.
Si la primera derivada tampoco se puede calcular, se estima una vez más numéricamente:
f ( x2 ) − f ( x1 )
f 0 (x) ' ,
x2 − x1
f ( x2 ) − f ( x1 )
x3 = x2 − γ
x2 − x1
f ( X0 + α D0 ) , α > 0,
77
Esta optimización unidimensional se denomina búsqueda lineal y el valor de α que
minimiza f ( X0 + α D0 ), α0 , se denomina longitud de paso.
3. Una vez se ha encontrado α0 tenemos una nueva estimación:
X1 = X0 + α0 D0
el proceso se repite de nuevo empezando por el punto 1 generando una secuencia de itera-
ciones:
$$X_{k+1}= X_{k} +\alpha_k D_k.$$
Los diferentes métodos para encontrar mínimos se diferencian en como escoger las direccio-
nes Dk .
La virtud de estos métodos es que remplazan el problema n-dimensional inicial por una
secuencia de problemas unidimensionales, más sencillos.
Dk = − ∇ f ( X )| X =Xk ,
Dk = − ∇ f ( X )| X =Xk + β k Dk−1 ,
donde:
∇ f ( X )T ∇ f (X ) Xk
βk = ,
∇ f (X )T ∇ f (X ) | X k −1
De esta forma las direcciones elegidas en cada iteración son conjugadas con respecto a la
matriz Hessiana de f ( x ):
DkT · H ( X )| XK · Dk−1 = 0.
Que implica que lo que bajamos en una dirección no lo deshacemos en las siguientes.
78
[17]: from [Link] import display,Image
display(Image("Conjugate_gradient.png",width=400))
79
80
El paquete scipy en su módulo optimize proporciona la función minimize donde se pueden esco-
ger diferentes método más avanzados:
Método de Brendt.
Método de Nelder–Mead.
Método de Powell.
Método BFGS.
[Link]
5. Ejercicio adicionales
5.1. Ejercicio 5.11: minimizando el potencial de ionización (Examen de Enero de 2023)
El potencial de ionización utilizado en un experimento para atrapar átomos viene dado por la
integral:
Z
1 1 1
Vion ≡ Vion (λ) = α cos2 + λ2 sin2 +y dx dy
D λ2 2xy − 1 xy
D ≡ ( x, y) x2 + y2 ≤ 1
[ ]:
5.2. Ejercicio 5.12: funciones complejas con polos (Examen de Junio de 2023)
Dada la función
g2
t(s) = , M = 0,75 GeV, g = 0,35 GeV,
M 2 − s + g2 J ( s )
2 σ(s) σ(s) − 1
J (s) = + log ,
π π σ(s) + 1
donde
81
r
sth
σ(s) = 1− , con sth = 4m2 , m = 0,140 GeV.
s
[ ]:
Por el tipo de proyectil sabemos que se trata de un cañón que dispara a una velocidad de 320 m/s
y que el ángulo con la horizontal al realizar el disparo es tal que se maximiza el alcance. Bajo estas
circunstancias se tiene que los proyectiles deben caer en los puntos que cumplen
82
( x − d )2 + ( y − c )2 = R2 ,
donde R es la distancia máxima alcanzada.
1. Considerando que la altura de lanzamiento y la de impacto son la misma, obtener la expre-
sión de R. Usando esta definir una función de python tal que represente el modelo x̃ (y|d, c),
donde d y c son los parámetros del modelo.
2. A partir del modelo, uno puede construir la función χ2 , definida como
donde el índice i hace referencia a los datos del archivo [Link]. Definir una función de
python que tome como entrada, por lo menos, los parámetros del modelo, es decir, d y c y
calcule el valor de χ2 (d, c).
3. Leer los datos contenidos en el fichero [Link] y representar en el plano los puntos de
impacto.
4. Construir una matriz que contenga el valor de χ2 (d, c) para distintos valores de los pará-
metros y representar mediante la función imshow. Mediante un proceso manual, ajustar los
límites del cuadrado [d0 , d1 ] × [c0 , c1 ], para localizar el mínimo de la función χ2 (d, c) de forma
aproximada.
AYUDA: limitar el valor máximo del colorbar puede ser útil para determinar la región del
mínimo.
Para tratar de localizar el mínimo vamos a usar el método del gradiente, para lo cual necesitamos
calcular el gradiente de la función χ2 (d, c).
5. Definir una función que determine el valor del gradiente de la función χ2 (d, c) en un punto
concreto y con un paso espacial determinado. Emplear un método de diferencias finitas para
determinar el valor del gradiente.
El método del gradiente para buscar mínimos de una función resulta un proceso iterativo,
donde a cada paso actualizamos el valor de los parámetros, de forma que:
siendo γ el ratio de aprendizaje. Dicho proceso iterativo se suele detener cuando la diferencia
en los parámetros entre una iteración y la siguiente es menor que una cierta tolerancia.
6. Tomando γ ∼ 0,01 definir una función que tome un punto aleatorio del cuadrado [d0 , d1 ] ×
[c0 , c1 ] y realice el proceso iterativo para encontrar el mínimo de la función χ2 (d, c).
7. Usando la función antes definida, repetir el proceso de búsqueda del mínimo para varios
puntos iniciales del cuadrado [d0 , d1 ] × [c0 , c1 ] y guardar los valores de los parámetros d y c
obtenidos cada vez.
8. Mediante el estudio estadístico de los resultados obtenidos determinar el valor de d y c, así
como el error.
83
[ ]:
JM
M = µ tanh ,
kB T
Cm
m = tanh .
T
Cogiendo C = 1, encontrar la solución de la ecuación más allá de la trivial, m=0, para temperaturas
0 < T < 2 K con una tolerancia para la solución e = 10−6 .
[ ]:
display(Image(filename="Finite_Square_Potential.png",width=600,height=600))
84
1. Usando las ecuaciones de Schrödinger probar que las energías permitidas de una partícula
de masa m atrapada en el pozo son las soluciones de
q p
tan L2 2
m E/2h̄ = p(V − E) / E para un número par de estados,
− E / (V − E) para un número impar de estados,
donde los estados están numerados empezando por 0, el estado fundamental, 1, el primer
estado excitado, etc.
2. Para un electrón, me = 9,1094 × 10−23 kg, en un pozo de profundidad V = 20 eV y anchura
L = 1 nm, representar en una misma gráfica las funciones
q q q
y1 = tan L2 m E/2h̄2 , y2 = (V − E) / E, y3 = − E / (V − E )
como función de E en el intervalo (0, 20) eV. A partir de la gráfica estimar el valor de los 6
primeros niveles de energía.
3. Escribir un programa que calcule los 6 primeros niveles de energía con una precisión de 10−6
usando el método de la bisección.
[ ]:
85
5.6. Ejercicio 5.16: el punto de Lagrange Tierra-Luna
El punto de Lagrange del sistema Tierra-Luna esta definido como aquel que siempre se encuentra
a la misma distancia entre ambos.
Es decir, aquel punto en el que un satélite orbitaria en torno a la Tierra en perfecta sincronía con la
Luna.
Esto se debe a que la atracción gravitatoria en ese punto debido a la Tierra y la Luna se combinan
para crear la fuerza centrípeta que mantiene al satélite en una órbita constante.
1. Asumiendo una orbita circular, probar que la distancia r desde el centro de la tierra al punto
de Lagrange L satisface:
GM Gm
− = ω 2 r,
r 2
( R − r )2
86
[ ]:
2 h ν3 c2
I (ν, T ) =
exp khBc Tν − 1
[ ]:
87