Está en la página 1de 31

20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

The Sage GIT21dgilpare Toggle Home Published Log Settings


Help Report a Problem Sign out
Notebook
Version 7.0

GIIT_AMA_2223_Practica6_dgilpare_calvarezju Save Save & quit Discard & quit


last edited Dec 20, 2022, 8:25:25 PM by GIT21dgilpare

File... Action... Data... sage  Typeset  Load 3-D Live  Use java for 3-D
Print Worksheet Edit Text Revisions Share Publish

Práctica 6. Métodos Numéricos. Parte I


Temporalización de la práctica: Lunes 5 de diciembre y Lunes 12 de diciembre de 2022

Entrega de la práctica: Desde el 12 de diciembre hasta el 19 de diciembre (ver tarea en el campus virtual
o agenda de la asignatura)

Instrucciones: 

1. Haz una copia de la hoja pública y renómbrala: si tu correo es mariomp@alumnos.unex.es añade al


final del título _mariomp, por ejemplo GIIT_AMA_2223_Practica6_mariomp 

Para cambiar el nombre pulsa en el título de la hoja (arriba del todo, entre el logo de Sage y el menú
"Archivo/File...")

2. Comparte la hoja de trabajo con el usuario mariomp2223 mediante el botón Compartir/Share de arriba a


la derecha. Si lo hacéis en pareja, compartid la hoja con el usuario de tu compañero (ambos usuarios
separados por comas), así como añadir también el usuario en el título de la hoja (separados por _).

3. Completa la primera celda y trabaja la práctica.

4. Cuando hayas terminado, haz una copia en un único fichero PDF y ponlo en el campus virtual (Si lo
hacéis en pareja, basta que lo suba uno). Esa será la versión que se evaluará. La hoja no se considera
entregada si no se ha renombrado y compartido (pasos 1 y 2).

Para generar el PDF lo más sencillo es usar el botón Imprimir/Print de arriba e imprimir la nueva
página a fichero.

5. Una vez subido el PDF al campus virtual, no podrá modificarse esta hoja de trabajo. Hacerlo conllevará
la calificación de 0 en esta práctica. 

6. Los ejercicios a entregar se representan en Rojo y deben estar correctamente explicados. Los ejercicios
indicados con ** NO serán obligatorios, pero aquellos que los hagan podrán ir sumando por cada uno de
ellos 0.1 puntos adicionales en la calificación de la práctica. 

Alumno/s: David Gil Parejo y Carmen Álvarez Murillo


Método de la Bisección
Comencemos definiendo una función de la que buscaremos una raíz en un intervalo concreto en el que sea
continua y cambie de signo, es decir, que cumpla el Teorema de Bolzano. El primer paso es definir la
función f(x) y representarla en un intervalo [a, b] para comprobar si en dicho intervalo se cumplen las
condiciones del Teorema de Bolzano. 
https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 1/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

f(x) = - x + cos(x)
print "f(x) = ", f(x)
        f(x) = -x + cos(x)

a, b = 0,1
plot(f(x),(x,a,b),figsize=4)

       

Podemos observar que la función

f(x) = − x + cos(x)

presenta una raíz en el intervalo [0,1], pues se cumplen las condiciones del Teorema de Bolzano. En Sage,
se puede encontrar la raíz de una función, f(x), en un intervalo [a, b] utilizando la función
find_root(f(x),a,b). Recordemos, además, que encontrar una raíz de una función no es más que resolver la
ecuación

f(x) = 0

, por lo que podemos aplicar también la función solve(f(x)==0,x), donde el primer argumento es la
ecuación a resolver (o varias ecuaciones), y el segundo argumento es la incógnita (o incógnitas). 

find_root(f(x),a,b)
        0.7390851332151559

solve(f(x)==0,x)
        [x == cos(x)]

Sin embargo, observamos que esta última opción nos muestra que esta ecuación no tiene una solución
exacta, por lo que habría que aplicar métodos numéricos para resolverla, o equivalentemente, la función no
tiene una raíz exacta y se debe aproximar, y por lo tanto, se debe asumir un cierto error.  

En métodos numéricos es necesario indicar el límite de error que podemos cometer (o asumir) para
encontrar una aproximación de la raíz buscada. Por ello, si llamamos error al error que se comete al aplicar
https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 2/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

un método numérico y err al error permitido que podemos asumir al aproximar la raíz, se debe cumplir que

error ≤ err

Nos podemos encontrar dos situaciones:

Situación 1. Que el error permitido sea un valor fijo, de modo que

error ≤ err

Situación 2. Que la raíz buscada tenga una precisión de d cifras decimales significativas, con lo cual, el
error permitido en este caso es

err = 0.5 ⋅ 10 − d

y por tanto,

error ≤ 0.5 ⋅ 10 − d

En particular, un primer método numérico es el método de la Bisección que consiste en encontrar la raíz de
una función en un intervalo [a, b] en el que la función cumple el Teorema de Bolzano, de tal modo que la
raíz considerada es el punto medio del intervalo

a+b
c=
2

c = (a+b)/2.0
print "La aproximación de la raíz es:", c
        La aproximación de la raíz es: 0.500000000000000

Como vemos con una primera iteración la aproximación de la raíz es bastante mala, teniendo en cuenta
cuál era el valor de la verdadera raíz mostrada anteriormente. Es por ello, que debemos hacer más
iteraciones para encontrar una mejor aproximación de la raíz. Por ejemplo, creemos un bucle (for) en el que
apliquemos el método de la Bisección n veces, por ejemplo n = 5.  

n = 5
for i in [1..n]:
print "Iteración:", i
print "Intervalo:", (a,b)
print "f(a) = ", f(a).n(digits=4)
print "f(b) = ", f(b).n(digits=4)
c = (a+b)/2.0
print "Aproximación de la raíz:", c.n(digits=4)
print "f(c) = ", f(c).n(digits=4)
if f(a)*f(c)<0: b = c
else: a = c
print
        Iteración: 1
Intervalo: (0, 1)
f(a) = 1.000
f(b) = -0.4597
Aproximación de la raíz: 0.5000

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 3/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

f(c) = 0.3776

Iteración: 2
Intervalo: (0.500000000000000, 1)
f(a) = 0.3776
f(b) = -0.4597
Aproximación de la raíz: 0.7500
f(c) = -0.01831

Iteración: 3
Intervalo: (0.500000000000000, 0.750000000000000)
f(a) = 0.3776
f(b) = -0.01831
Aproximación de la raíz: 0.6250
f(c) = 0.1860

Iteración: 4
Intervalo: (0.625000000000000, 0.750000000000000)
f(a) = 0.1860
f(b) = -0.01831
Aproximación de la raíz: 0.6875
f(c) = 0.08533

Iteración: 5
Intervalo: (0.687500000000000, 0.750000000000000)
f(a) = 0.08533
f(b) = -0.01831
Aproximación de la raíz: 0.7188
f(c) = 0.03388

Observamos que con 5 iteraciones, hemos encontrado una aproximación de la raíz de 0.7188, ya más
próxima al verdadero valor de la raíz. En relación al error, en el método de la Bisección, si se quiere buscar
una raíz de una función en el intervalo [a, b], el error que se comete en la iteración n es:

b−a
error n =
2n

Siguiendo el ejemplo anterior, el error que se comete en la iteración 5 es:

1−0
error 5 =
25

a,b,n = 0,1,5
error = (b-a)/2^n; print "Error cometido:", error.n(digits=4)
        Error cometido: 0.03125

De manera general, si se debe cumplir que el error cometido sea inferior al error permitido, entonces

error n ≤ err

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 4/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

luego,

b−a
≤ err
2n

y por tanto, despejando n, se tiene que

n≥
log
( )
b−a
err
log2

De forma que para encontrar una raíz de la función f(x) en el intervalo [a, b] cuyo error cometido sea
inferior al error permitido err es necesario realizar n iteraciones, donde n debe ser mayor o igual a

log ( )
b−a
err
log2

Por tanto, veamos cuántas iteraciones (n) son necesarias para encontrar una raíz de la función
f(x) = − x + cos(x) en el intervalo [0, 1] con un error permitido err = 0.05. 

f(x) = -x+cos(x); a,b = 0,1


err = 0.05
n = log((b-a)/err)/log(2.0)
print "n >=", n
        n >= 4.32192809488736

Además, vemos que el valor de n debe ser mayor o igual a 4.32, y como n es el número de iteraciones, y
por tanto un número entero, debemos redondear por exceso este último valor, por lo que utilizaremos la
función .ceil().

n = n.ceil()
print "Iteraciones necesarias:", n
        Iteraciones necesarias: 18

Por otro lado, si queremos una aproximación de la raíz con una precisión de d = 5 cifras decimales
significativas, entonces el error permitido será

error n ≤ 0.5 ⋅ 10 − 5

por tanto

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 5/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

f(x) = -x+cos(x); a,b = 0,1


d = 5
err = 0.5*10^(-d)
n = log((b-a)/err)/log(2.0)
n = n.ceil()
print "Iteraciones necesarias:", n
        Iteraciones necesarias: 18

Vemos que en esta ocasión es necesario realizar 18 iteraciones.

Ejercicio 1. Crea una función que aplique el método de la Bisección para encontrar
una aproximación de la raíz de una función f(x) en un intervalo [a, b] cuyo error
permitido sea err, por ello la función debe recibir como argumentos f(x), los valores
a, b y el error err, y debe devolver la aproximación encontrada de la raíz, c, y el error
que se ha cometido al encontrarla. 

El siguiente algoritmo consiste en lo siguiente:

En primer lugar calculamos el número de iteraciones necesarias mediante la fórmula que se incluye
en el código.

Seguidamente, basándonos en el número de iteraciones calculamos el error cometido

Finalmente calculamos la aproximación, para ello creamos un bucle que se ejecute para cada
iteración y que consiste en:

1. Calcular el punto medio entre a y b

2. Realizar su producto, esto nos sirve para averiguar si si signo es igual (el producto saldría
positivo) o si son distintos (producto negativo).

Signo positivo: Se vuelve a realizar el bucle entre el centro previamente calculado y b (a=c)
Signo negativo: Se vuelve a realizar el bucle entre el centro previamente calculado y a
(b=c)

def Biseccion(f,a,b,err):
n = log((b-a)/err)/log(2.0)
n=n.ceil()
print "Iteraciones necesarias:", n
error = (b-a)/2^n
print "Error cometido:", error.n(digits=4)
for i in [0..n-1]:
c=(a+b)/2.0
z=f(c)*f(a)
if z>0:
a=c
else:
b=c
print "Aproximacion: ",c
       

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 6/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

Ejercicio 2. Dada la función 

( (
f(x) = e − x − sin x ⋅ 1 +
1
log(dni) ))
siendo dni la suma de los números de tu DNI. Aplicando la función creada en el
ejercicio anterior, encuentra una aproximación de la raíz de la función en el intervalo
[0, 1] con una precisión de 5 cifras decimales significativas. 

DNI=80230317, Suma de cifras= 24

Procedemos a pintar la función en un intervale en el que esta cambie de signo:

f(x)=e^(-x)-sin(x*(1+((1)/(log(24.0)))))
a, b = 0,1
plot(f(x),(x,a,b),figsize=4,color='orange',thickness=2)

       

Según el Teorema de Bolzano, si nos fijamos en la gráfica anterior observamos que al cambiar de
signo en el intervalo [0,1], existe una raíz en este intervalo, por lo que podemos realizar el método de
la bisección entre estos dos puntos.

f=f(x)
err=0.5*10^(-5)
Biseccion(f,0,1,err)
Iteraciones necesarias: 18
        Error cometido: 3.815e-6
Aproximacion: 0.497287750244141

Ejercicio 3. Sea la ecuación

x ⋅ sin(x) + 2lnx + x = 2.6

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 7/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

aplica el método de la Bisección para encontrar una solución de la ecuación con una
precisión de 4 cifras decimales significativas. 

Procedemos a pintar la función en un intervale en el que esta cambie de signo:

f(x)=x*sin(x)+2*ln(x)+x-2.6
a, b = 1,2
plot(f(x),(x,a,b),figsize=4,color='purple',thickness=2)

       

Según el Teorema de Bolzano, si nos fijamos en la gráfica anterior observamos que cambia de signo
en el intervalo [1,2], por lo que existe una raíz en este intervalo. Este intervalo lo hemos encontrando
probando valores.

A continuación procedemos a realizar el método de la bisección entre estos dos puntos.

f=f(x)
err=0.5*10^(-4)
Biseccion(f,1,2,err)
Iteraciones necesarias: 15
        Error cometido: 0.00003052
Aproximacion: 1.17947387695312

** Ejercicio 4. La concentración de una bacteria contaminante en un líquido


disminuye a lo largo del tiempo según la expresión:

f(x) = 80 ⋅ e − 2x + 20 ⋅ e − 0.5x − 5

siendo x el tiempo en horas. Aplica el método de la Bisección para determinar el


tiempo (en minutos) necesario para que la concentración se reduzca prácticamente a
0. 

Procedemos a pintar la función en un intervale en el que esta cambie de signo:

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 8/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

f(x)=80*e^(-2*x)+20*e^(-0.5*x)-5
a, b = 2,3
plot(f(x),(x,a,b),figsize=4,color='green',thickness=2)

       

Según el Teorema de Bolzano, si nos fijamos en la gráfica anterior observamos que cambia de signo
en el intervalo [2,3], por lo que existe una raíz en este intervalo. Este intervalo lo hemos encontrando
probando valores.

A continuación procedemos a realizar el método de la bisección entre estos dos puntos.

f=f(x)
err=0.5*10^(-4)
Biseccion(f,2,3,err)
Iteraciones necesarias: 15
        Error cometido: 0.00003052
Aproximacion: 2.99996948242188

Observamos que la aproximación en horas con un error de 4 cifras significativas es


2.87673950195312, pero lo que se nos pide es el valor en minutos, por lo que:

x=2.87673950195312
x=x*60
print 'Tiempo necesario en minutos para que la concentración se reduzca
prácticamente a 0 con un error de 4 cifras significativas: ',x
Tiempo necesario en minutos para que la concentración se reduzca
        prácticamente a 0 con un error de 4 cifras significativas:
172.604370117187

Método de Newton

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 9/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

Si recordamos el método de la Bisección para encontrar la raíz de una función es necesario conocer
previamente el intervalo en el que se encuentra la raíz. Este problema se salva utilizando el método de
Newton, pues basta conocer un punto inicial x 0 en el que comenzar a determinar la sucesión de números
que convergerá a la raíz buscada. Consideremos la función

f(x) = e x − 4

veamos dónde se encuentra la raíz para considerar un valor inicial óptimo. 

f(x) = e^x - 4
plot(f(x),x,figsize=4)

       

Por defecto, la función plot(f(x),x) representa la función f(x) en el intervalo [0, 1]. Además, observamos
que en él, la función no tiene raices, por lo que vamos a modificar el intervalo de representación. 

plot(f(x),(x,0,4),figsize=4)

       

Vemos que la raíz se encuentra en el intervalo [1,2], entonces vamos a considerar como valor inicial
óptimo un valor de ese intervalo, por ejemplo el punto medio. Además, para poder aplicar el método de
Newton es necesario calcular la derivada de la función f(x), utilizando la función .diff(x). 
https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 10/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

f(x) = e^x - 4
derf(x) = f.diff(x)
print "f(x) = ", f(x)
print "f'(x) = ", derf(x)
f(x) = e^x - 4
       
f'(x) = e^x

a,b = 1,2
x0 = (a+b)/2.0
print "x0 = ", x0.n(digits=4)
        x0 = 1.500

Por tanto, como el método de Newton construye una sucesión numérica x n del siguiente modo:

f(x n − 1)
xn = xn − 1 − ′
f (x n − 1)

por lo que en cada iteración n, para encontrar una aproximación de la raíz (x n) solo es necesario conocer el
valor aproximado de la raíz en la iteración anterior x n − 1.

x1 = x0 - f(x0)/derf(x0)
print "Iteración 1:"
print "Aproximación de la raíz:", x1.n(digits=5)
Iteración 1:
       
Aproximación de la raíz: 1.3925

En el caso particular del método de Newton, el error que se comete en la iteración n será

error n = | x n − x n − 1|

es decir, será la diferencia, en valor absoluto, entre la aproximación obtenida en la iteración n y la obtenida
en la iteración n-1.

error = abs(x1-x0)
print "Error cometido en la iteración 1:", error.n(digits=5)
        Error cometido en la iteración 1: 0.10748

Observamos que con 1 iteración el error que se comete es, aproximadamente, 0.11.

Ejercicio 5. Crea una función que aplique el método de Newton para encontrar una
aproximación de una raíz de una función f(x) partiendo de un valor inicial x0 y con un
error permitido err, esto es, debe recibir como argumentos la función f(x), el valor
inicial x0, y el error err, y debe devolver la aproximación de la raíz encontrada xn, así
https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 11/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

como el error que se comete al encontrarla. En esta ocasión, para que se cumpla el
error utiliza while.

El siguiente algoritmo consiste en lo siguiente:

Inicializamos el contador a 1

Calculamos la derivada de la función

Calculamos la aproximación de la raíz y el error cometido mediante las fórmulas que se indican en el
código 

Imprimimos por pantalla el número de iteración, la aproximación de la raíz y el error cometido en la


iteración correspondiente.

A continuación hacemos un bucle mientras que el error cometido sea mayor que el permitido:

Calculamos el absoluto de la diferencia entre x1 y x0 (la aproximación de la raíz y el valor


inicial)

Si el resultado es menor al error permitido, devolvemos x1 y el error cometido

Incrementamos el contador

Ahora x0 pasa a ser x1

Volvemos a realizar las fórmulas para calcular el error cometido y la aproximación de la raíz

Imprimimos por pantalla el número de iteración, la aproximación de la raíz y el error cometido


en la iteración

El bucle devuelve la aproximación de la raíz y el error cometido

def Newton(f,x0,err):
cont=1
f(x)=f
derf(x)=f.diff(x)
x1 = x0 - f(x0)/derf(x0)
print "Iteración ",cont,":"
print "Aproximación de la raíz:", x1.n(digits=5)
errorx = abs(x1-x0)
print "Error cometido en la iteración ",cont,":", errorx.n(digits=5)
while errorx>err:
errorcomp = abs(x1-x0)
if errorcomp<err:
return x1,errorx
cont=cont+1
x0=x1
x1=x0-f(x0)/derf(x0)
print "Iteración ",cont,":"
print "Aproximación de la raíz:", x1.n(digits=5)
errorx = abs(x1-x0)
print "Error cometido en la iteración ",cont,":",
errorx.n(digits=5)
       

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 12/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

Ejercicio 6. Utiliza el método de Newton para resolver la ecuación

ln(x 2) = 0.7

para obtener una aproximación de la raíz positiva con un error máximo permitido de
0.05. Considera el valor inicial x 0 que desees. 

Representamos la función en el intervalo 0,4 para ver dónde corta en el eje X:

f(x)=ln(x^2)-0.7
plot(f(x),(x,0,4),figsize=4)

       

Cogemos el punto medio del intervalo a,b=1,2:

a,b = 1,2
x0 = (a+b)/2.0
print "x0 = ", x0.n(digits=4)
        x0 = 1.500

f=f(x)
err=0.05
Newton(f,x0,err)
Iteración 1 :
Aproximación de la raíz: 1.4168
Error cometido en la iteración 1 : 0.083198
        Iteración 2 :
Aproximación de la raíz: 1.4191
Error cometido en la iteración 2 : 0.0022634
(1.41906573968987, 0.00226340185211593)

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 13/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

Ejercicio 7. Sea la función

f(x) = 3x 3 − 5x 2 + 2x − 4

a) Utilizando el método de la Bisección, encuentra una aproximación de la raíz


positiva, en el intervalo correspondiente [a, b], con un error máximo permitido de
0.05. ¿Qué error se comete al encontrar dicha aproximación?

b) Utilizando el método de Newton, y considerando el valor inicial como el punto


medio del intervalo [a, b] del apartado anterior, encuentra una aproximación de la
raíz positiva con un error máximo permitido de 0.05. ¿Qué error se comete al
encontrar dicha aproximación?

c) Observando los resultados anteriores, ¿cuál de los dos métodos numéricos


proporciona una aproximación de la raíz más precisa? 
En primer lugar representamos la función para observar en que intervalo cambia de signo:

f(x)=3*x^3-5*x^2+2*x-4
a, b = 1,2
plot(f(x),(x,a,b),figsize=4,color='blue',thickness=2)

       

Según el Teorema de Bolzano, si nos fijamos en la gráfica anterior observamos que cambia de signo
en el intervalo [1,2], por lo que existe una raíz en este intervalo. Este intervalo lo hemos encontrando
probando valores.

a) En primer lugar vamos a usar el método de la bisección para encontrar un aproximación positiva
de la raíz en el intervalo hallado [1,2] con un error máximo de 0.05

f=f(x)
err=0.05
Biseccion(f,1,2,err)
        Iteraciones necesarias: 5
Error cometido: 0.03125

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 14/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

Aproximacion: 1.71875000000000

b) Ahora, utilizaremos el método de Newton y consideraremos el valor inicial como el punto medio
del intervalo [1,2]. 

Calculamos el punto medio del intervalo [a,b]=[1,2]:

a,b = 1,2
x0 = (a+b)/2.0
       

err=0.05
Newton(f,x0,err)
Iteración 1 :
Aproximación de la raíz: 1.7931
Error cometido en la iteración 1 : 0.29310
Iteración 2 :
Aproximación de la raíz: 1.7311
       
Error cometido en la iteración 2 : 0.061954
Iteración 3 :
Aproximación de la raíz: 1.7275
Error cometido en la iteración 3 : 0.0036052
(1.72754407961281, 0.00360515652062965)

c) Es mejor la aproximación mediante el método de Newton porque el error es menor.

       

Vectores y Matrices
Antes de comenzar a trabajar con Sistemas de Ecuaciones Lineales, es necesario hacer un repaso previo a
cómo construir vectores y matrices en Sage, así como las distintas operaciones que podemos realizar con
ellas. 

En primer lugar, para crear vectores en Sage utilizamos la función vector() que permite considerar como
vector una lista de números. Como observamos se trata de un vector con números enteros, pero
normalmente nos interesa trabajar con valores reales, para ello, y de manera generalizada, se puede
añadir RDF como primer argumento a la función vector(). 

v = vector([1,2,3,4]); print v
v = vector(RDF,[1,2,3,4]); show(v)
(1, 2, 3, 4)
       
(1.0, 2.0, 3.0, 4.0)

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 15/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

Por otro lado, para construir matrices en Sage se emplea la función matrix(), al igual que ocurre con los
vectores si se queremos trabajar con números reales debemos situar como primer argumento el valor RDF.
Ahora bien, las matrices se crean como una lista de listas, esto es, una lista cuyos elementos serán listas
que representen los elementos de una fila. 

A = matrix(RDF,[[1,2,4,3],[2,1,4,5],[3,4,1,6],[4,5,1,7]])
show(A)

( )
1.0 2.0 4.0 3.0
        2.0 1.0 4.0 5.0
3.0 4.0 1.0 6.0
4.0 5.0 1.0 7.0

Por otro lado, para hacer referencia a un elemento de una matriz, se debe indicar la posición de dicho
elemento entre corchetes, de modo que el elemento de la fila 1 y columna 1 se corresponde al valor A[0,0]. 

A[0,0]
        1.0

Para trabajar con filas o columnas enteras de una matriz se utiliza el símbolo : para indicar que se toman
todos los elementos según se sitúe [:,a] o [a,:] que indica seleccionar todos los elementos de la columna o
de la fila (respectivamente) a+1. 

A[:,1] #Columna 2
[2.0]
[1.0]
       
[4.0]
[5.0]

A[1,:] #Fila 2
        [2.0 1.0 4.0 5.0]

En Sage podemos obtener los elementos de la diagonal de la matriz empleando la función .diagonal(), y


además la función diagonal_matrix(x) permite construir una matriz diagonal cuyos elementos se
encuentran en la lista x.

diag = A.diagonal(); show(diag)


D = diagonal_matrix(diag); show(D)
       
[1.0, 1.0, 1.0, 7.0]
https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 16/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

( )
1.0 0.0 0.0 0.0
0.0 1.0 0.0 0.0
0.0 0.0 1.0 0.0
0.0 0.0 0.0 7.0

Sistemas de Ecuaciones Lineales


Dado una matriz de coeficientes A, un vector de incógnitas x y un vector de términos independientes b, se
puede construir un sistema de ecuaciones lineales de modo matricial como

Ax = b

Si la matriz A tiene inversa (esto es, su determinante es no nulo), entonces se puede obtener el vector de
incógnitas como

x = A − 1b

Como observamos para encontrar el vector de soluciones x multiplicamos por la derecha la matriz A al
vector b, por ello en Sage puede resolverse el sistema de ecuaciones lineales utilizando la
función .solve_right().

Por ejemplo, consideremos el sistema de ecuaciones lineales:

}
x+z =1
2x + y =2
− x + y − 2z =3

A = matrix(RDF,[[1,0,1],[2,1,0],[-1,1,-2]]); show(A)
b = vector(RDF,[1,2,3]); show(b)
x = A.solve_right(b); show(x)

( )
1.0 0.0 1.0
2.0 1.0 0.0
        − 1.0 1.0 − 2.0

(1.0, 2.0, 3.0)

( − 3.0, 8.0, 4.0)

Métodos Iterativos 
https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 17/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

Cuando se trata de un sistema de ecuaciones lineales de grandes dimensiones, los métodos de Gauss y
Gauss con pivoteo parcial requieren muchas operaciones y son muy sensibles a errores de redondeo, por lo
que no son muy adecuados para resolver este tipo de sistemas. 

Para resolver sistemas de ecuaciones lineales con grandes dimensiones, o sistemas en los que la matriz de
coeficientes es dispersa (es decir, presenta muchos ceros), se utilizan métodos iterativos que construyen
una sucesión de vectores x 0, x 1, . . . que converjan al vector solución del sistema x.

Estos métodos se basan en el método del Punto Fijo para variables n dimesionales. 

Sea el sistema de ecuaciones lineales:

Ax = b

es fácil escribir la matriz de coeficientes A como una diferencia de dos matrices M y N, tal que

A=M−N

De este modo, se puede escribir el sistema como

(M − N)x = b

o equivalentemente

Mx = Nx + b

 por lo tanto,

x = M − 1(Nx + b)

Si denotamos por F(x) = M − 1(Nx + b), entonces tenemos que x = F(x), esto es, ya hemos conseguido la
función del punto fijo. Por lo tanto, todo método iterativo se construye de la forma

x = M − 1(Nx + b)

con A = M − N. Dependiendo de cómo se considere las matrices M y N se obtiene un método iterativo u


otro. 

Por tanto, para un vector inicial x 0, en la iteración n se obtiene una aproximación del vector solución

x n = M − 1(Nx n − 1 + b)

Finalmente, remarcar que para poder aplicar el método iterativo es necesario: 

1) Que M tenga determinante no nulo. 

2) Que la solución que se construye converja al vector solución del sistema x. 

Convergencia de los métodos iterativos

Sea la matriz de coeficientes A del sistema de ecuaciones Ax = b, si

A es diagonalmente dominante, o,
A t es diagonalmente dominante, o, 
A es simétrica y definida positiva,
https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 18/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

entonces existe una única solución del sistema y los métodos iterativos producen una sucesión de vectores
que converge a dicha solución. 

Recordemos que una matriz A es diagonalmente dominante si:


n

|a kk | > ∑ | a kj | , k = 1, 2, . . . , n
j=1,j≠k

La función creada is_diagonally_dominant(A) comprueba si la matriz A es diagonalmente dominante. 

A = matrix(RDF,[[2,-1,0],[1,6,-2],[4,-3,8]]); show(A)

( )
2.0 − 1.0 0.0
        1.0 6.0 − 2.0
4.0 − 3.0 8.0

def is_diagonally_dominant(A):
n = A.dimensions()[0]
is_dd = True
for k in [0..(n-1)]:
s = - abs(A[k,k])
for j in [0..(n-1)]:
s = s + abs(A[k,j])
if abs(A[k,k])<=s:
is_dd = False
return is_dd
return is_dd
       

is_diagonally_dominant(A)
        True

Para comprobar, en Sage, si la matriz es simétrica y definida positiva existen las


funciones .is_symmetric() y .is_positive_definite(). 

A.is_symmetric()
        False

A.is_positive_definite()
        False

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 19/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

Ejercicio 8. Sea la matriz

( )
4 1 1
−2 3 1
1 1 3

Comprueba si dicha matriz permite construir una sucesión de vectores convergente


utilizando métodos iterativos. 

Para saber si permite construir una sucesión de vectores convergente utilizando métodos iterativos,
se tiene que cumplir al menos una de las siguientes condiciones:

1. Que A sea diagonalmente dominante


2. Que A t sea diagonalmente dominante
3. Que A sea simétrica y definida positiva

Vamos a comprobar en primer lugar si A es diagonalmente dominante: 

A = matrix(RDF,[[4,1,1],[-2,3,1],[1,1,3]])
is_diagonally_dominant(A)
        False

Observamos que no es diagonalmente dominante, entonces pasamos a comprobar si la traspuesta de


A lo es:

At=matrix(RDF,[[4,-2,1],[1,3,1],[1,1,3]])
is_diagonally_dominant(At)
        True

Como si lo es, podemos concluir con que la matriz A si que permite construir una sucesión de
vectores convergente utilizando métodos iterativos.

Por otro lado, una matriz A lleva asociada tres matrices D, L y U, tales que

A=D+L+U

donde 

D es una matriz diagonal: se construye con la diagonal de A.


L es una matriz triangular inferior: se construye con los elementos que están por debajo de la
diagonal de la matriz A, en la diagonal y por encima se encuentra formada por 0.
U es una matriz triangular superior: se construye con los elementos que están por encima de la
diagonal de la matriz A, en la diagonal y por debajo se encuentra formada por 0.

A = matrix(RDF,[[2,-1,3],[1,6,-1],[4,-1,3]]); show(A)
       

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 20/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

( )
2.0 − 1.0 3.0
1.0 6.0 − 1.0
4.0 − 1.0 3.0

Para construir la matriz D se utiliza la función diagonal_matrix(), mientras que para obtener las matrices L
y U empleamos las funciones creadas lower_triangular_matrix() y upper_triangular_matrix(),
respectivamente. 

D = diagonal_matrix(A.diagonal()); show(D)

( )
2.0 0.0 0.0
        0.0 6.0 0.0
0.0 0.0 3.0

def lower_triangular_matrix(A):
n = A.dimensions()[0]
L = matrix(RDF,n,n)
for k in [1..(n-1)]:
for j in [0..(k-1)]:
L[k,j] = A[k,j]
return L
       

L = lower_triangular_matrix(A); show(L)

( )
0.0 0.0 0.0
        1.0 0.0 0.0
4.0 − 1.0 0.0

def upper_triangular_matrix(A):
n = A.dimensions()[0]
U = matrix(RDF,n,n)
for k in [0..(n-2)]:
for j in [(k+1)..(n-1)]:
U[k,j] = A[k,j]
return U
       

U = upper_triangular_matrix(A); show(U)
       
https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 21/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

( )
0.0 − 1.0 3.0
0.0 0.0 − 1.0
0.0 0.0 0.0

Método Iterativo de Jacobi

El método de Jacobi es un método iterativo en el que las matrices M y N son

M=D

N = − (L + U)

de modo que la sucesión se construye partiendo del valor inicial x 0 tal que para la iteración n es:

Dx n = − (L + U)x n − 1 + b

Sea el sistema de ecuaciones lineales

}
2x − y =9
x + 6y − 2z = 15
4x − 3y + 8z =1

vamos a aplicar el método de Jacobi partiendo del valor inicial x 0 = (0, 0, 0). 

x0 = vector(RDF,3); print "x0: "; show(x0)


A = matrix(RDF,[[2,-1,0],[1,6,-2],[4,-3,8]]); print "A:"; show(A)
b = vector(RDF,[9,15,1]); print "b:"; show(b)
x0:

(0.0, 0.0, 0.0)

A:

( )
2.0 − 1.0 0.0
       
1.0 6.0 − 2.0
4.0 − 3.0 8.0

b:

(9.0, 15.0, 1.0)

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 22/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

D = diagonal_matrix(A.diagonal()); print "D:"; show(D)


L = lower_triangular_matrix(A); print "L:"; show(L)
U = upper_triangular_matrix(A); print "U:"; show(U)
D:

( )
2.0 0.0 0.0
0.0 6.0 0.0
0.0 0.0 8.0

L:

( )
0.0 0.0 0.0
       
1.0 0.0 0.0
4.0 − 3.0 0.0

U:

( )
0.0 − 1.0 0.0
0.0 0.0 − 2.0
0.0 0.0 0.0

M = D; print "M:"; show(M)


N = -(L+U); print "N:"; show(N)
M:

( )
2.0 0.0 0.0
0.0 6.0 0.0
0.0 0.0 8.0

       
N:

( )
− 0.0 1.0 − 0.0
− 1.0 − 0.0 2.0
− 4.0 3.0 − 0.0

x1 = M.solve_right(N*x0+b)
print "Aproximación del vector solución en la iteración 1:"; show(x1)
Aproximación del vector solución en la iteración 1:
       
(4.5, 2.5, 0.125)

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 23/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

Veamos cuál es la solución real del sistema de ecuaciones Ax = b, para comprobar cómo de precisa es la
aproximación x 1 obtenida. Se puede concluir que la aproximación de la primera incógnita es próxima al
valor real, pero no así con las otras dos incógnitas. Por ello, será necesario seguir realizando iteraciones. 

A.solve_right(b)
       

n = 4
x0 = vector(RDF,3); print "x0:", x0
for i in [1..n]:
x1 = M.solve_right(N*x0+b)
print "Iteración ",i," :"
print "Aproximación del vector solución:"
show(x1)
x0 = x1
print
       

Ejercicio 9. Crea una función que reciba una matriz A, el vector de términos
independientes b, el número de iteraciones n, y un valor inicial x0, y muestre por
pantalla las soluciones del sistema Ax = b obtenidas cada una de las n iteraciones del
método de Jacobi. 

def Jacobi(A,b,n,x0):
print "Iteración",i
x1 = M.solve_right(N*x0+b)
print "Solución:", x1
error = map(abs,x0-x1)
print "Errores:", error
x0 = x1
error = max(error)
i = i+1
print
       

Método Iterativo de Gauss-Seidel

El método de Gauss-Seidel es un método iterativo en el que las matrices M y N son:

M=D+L

N= −U

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 24/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

de modo que la sucesión se construye partiendo del valor inicial x 0 tal que para la iteración n es

(D + L)x n = − Ux n − 1 + b

Sea el sistema de ecuaciones lineales

}
2x − y =9
x + 6y − 2z = 15
4x − 3y + 8z =1

vamos a aplicar el método de Jacobi partiendo del valor inicial x 0 = (0, 0, 0). 

x0 = vector(RDF,3); print "x0: "; show(x0)


A = matrix(RDF,[[2,-1,0],[1,6,-2],[4,-3,8]]); print "A:"; show(A)
b = vector(RDF,[9,15,1]); print "b:"; show(b)
       

D = diagonal_matrix(A.diagonal()); print "D:"; show(D)


L = lower_triangular_matrix(A); print "L:"; show(L)
U = upper_triangular_matrix(A); print "U:"; show(U)
       

M = D+L; print "M:"; show(M)


N = -U; print "N:"; show(N)
       

n = 4
x0 = vector(RDF,3); print "x0:", x0
for i in [1..n]:
x1 = M.solve_right(N*x0+b)
print "Iteración ",i," :"
print "Aproximación del vector solución:"
show(x1)
x0 = x1
print
       

Ejercicio 10. Crea una función que reciba una matriz A, el vector de términos
independientes b, y el número de iteraciones n, y un valor inicial x0, y muestre por
pantalla las soluciones del sistema Ax = b obtenidas cada una de las n iteraciones del
método de Gauss-Seidel. 

def Gauss(A,b,n,x0):
       

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 25/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

Ejercicio 11. Sea el sistema de ecuaciones lineales

}
5x + y + 3t =4
3x + 7y − 2z + t = −2
2x + y + 9z − 3t =1
x + 2y + 4t =0

partiendo del valor inicial (0, 0, 0, 0),

a) Aplica 7 iteraciones  del método de Jacobi para resolver el sistema. 

b) Aplica 7 iteraciones del método de Gauss-Seidel para resolver el sistema. 

#Realiza el ejercicio en esta celda


       

** Ejercicio 12. Sea el sistema de ecuaciones lineales

}
4x − y + z =7
4x − 8y + z = − 21
− 2x + y + 5z = 15

partiendo del valor inicial (0, 0, 0), aplica 5 iteraciones:

a) Del método de Gauss-Seidel para resolver el sistema.

b) Del método de Jacobi para resolver el sistema.

#Realiza el ejercicio en esta celda


       

Sistemas de Ecuaciones No Lineales: Método de Newton

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 26/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

Los sistemas de ecuaciones lineales no son los únicos que pueden aparecer en situaciones reales, es más
son poco habituales. En general, en estas situaciones suelen aparecer sistemas de ecuaciones no lineales,
como por ejemplo:

x3 − y2
x 2 + 2y 2 − 1
=0
=0 }
Este tipo de sistemas de ecuaciones no lineal, se puede escribir como:

}
f 1(x 1, x 2, . . . , x n) =0
f 2(x 1, x 2, . . . , x n) =0
...
f n(x 1, x 2, . . . , x n) =0

Si denotamos por

( )
f 1(x 1, . . . , x n)
f 2(x 1, . . . , x n)
F(x 1, x 2, . . . , x n) =
...
f n(x 1, . . . , x n)

el sistema de ecuaciones no lineales queda de la forma

F(x 1, . . . , x n) = 0

donde 0 = (0, 0, . . . , 0). 

Esta última notación nos lleva a pensar realmente buscar una solución del sistema de ecuaciones no
lineales es equivalente a buscar una raíz de la función F. Para ello, vamos a aplicar el método de Newton,
partiendo de un valor inicial x 0 para una iteración n:

x n = x n − 1 − J − 1(x n − 1)F(x n − 1)

donde J(x) es la matriz jacobiana de la función F(x). Equivalentemente, se tiene el siguiente sistema de
ecuaciones: 

J(x n − 1)(x n − x n − 1) = − F(x n − 1)

Remarcar que este sistema es lineal. 

Resumiendo, y denotando por x d = x n − x n − 1, se tiene el sistema de ecuaciones lineales:

J(x n − 1)x d = − F(x n)

que nos permite encontrar la solución x d, sin embargo ésta no es la solución del sistema de ecuaciones no

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 27/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

lineales, para encontrarla es necesario realizar posteriormente:

xn = xn − 1 + xd

Para determinar la matriz jacobiana de una función F se puede calcular en Sage con la
función .derivative(). 

F(x,y) = (x^3-y^2,x^2+2*y^2-1); F(x,y)


       

J = F.derivative(); show(J)
       

x0 = vector(RDF,[1,1]); print "x0:"; show(x0)


print "J(x,y):"; show(J)
       

print "J(x0,y0):"; show(J(x0[0],x0[1]))


       

print "-F(x0,y0):"; show(-F(x0[0],x0[1]))


       

Jx0 = J(x0[0],x0[1]); Fx0 = - F(x0[0],x0[1])


xd = Jx0.solve_right(Fx0)
print "xd:"; show(xd)
       

x1 = x0 + xd
print "Aproximación de la solución en la iteración 1:"; show(x1)
       

Recordemos que este es un método iterativo, por lo que habrá que seguir realizando iteraciones hasta
encontrar una solución próxima a la real. 

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 28/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

n = 4
x0 = vector(RDF,[1,1])
F(x,y) = (x^3-y^2,x^2+2*y^2-1)
J = F.derivative()
for i in [1..n]:
print "Iteración ",i,":"
print
Jxi = J(x0[0],x0[1])
Fxi = -F(x0[0],x0[1])
xd = Jxi.solve_right(Fxi)
#print "Aproximación de la solución del sistema lineal:"
#print xd
#print
x1 = x0 + xd
print "Aproximación de la solución del sistema No lineal:"
print x1
print
x0 = x1
       

Ejercicio 13. Sea DNI la suma de los números de tu DNI, a la última cifra de tu DNI y
dni = DNI / 2.9 ln ( DNI ) Aplica 5 iteraciones del método de Newton, partiendo del valor
(1, 1, 1) para resolver el siguiente sistema de ecuaciones no lineales:

}
(12 + dni)x − y 3 − e z =1
− sin(x) + (10 + a)y − 2z =2
− 2x − cos(y) + 16sin(z) =3

DNI= sum([0,9.0,2,0,9,5,9,1])
a=9
dni=DNI/(2.9^ln(DNI))
dni
        0.794478627984637

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 29/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

n=5
x0=vector(RDF,[1,1,1])
F(x,y,z)=((12+dni)*x-y^3-e^z-1,-sin(x)+(10+a)*y-2*z,-2*x-
cos(y)+16*sin(z)-3)
J = F.derivative()
for i in [1..n]:
print "Iteración ",i,":"
print
Jxi = J(x0[0],x0[1],x0[2])
Fxi = -F(x0[0],x0[1],x0[2])
xd = Jxi.solve_right(Fxi)
#print "Aproximación de la solución del sistema lineal:"
x1 = x0 + xd
print "Aproximación de la solución del sistema No lineal:"
print x1
print
Iteración 1 :

Aproximación de la solución del sistema No lineal:


(-0.0922319041215569, 0.005604466290997423, -0.07242535446965981)

Iteración 2 :

Aproximación de la solución del sistema No lineal:


(0.17595613216741884, 0.03792605083910932, 0.2728240082853116)

Iteración 3 :
       
Aproximación de la solución del sistema No lineal:
(0.18117352574640072, 0.03854593080376345, 0.27609313182697315)

Iteración 4 :

Aproximación de la solución del sistema No lineal:


(0.18117424149019085, 0.03854600783203709, 0.27609471449560957)

Iteración 5 :

Aproximación de la solución del sistema No lineal:


(0.18117424149035868, 0.03854600783208296, 0.2760947144959859)

Ejercicio 14. Aplica 5 iteraciones del método de Newton, partiendo del valor (1, 1)
para resolver el siguiente sistema de ecuaciones no lineales:

xy 3 − 2y
y2 + x + y
= −1
=1 }
https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 30/31
20/12/22, 21:33 GIIT_AMA_2223_Practica6_dgilpare_calvarezju -- Sage

n=5
x0=vector(RDF,[1,1])
F(x,y)=(x*y^3-2*y+1,y^2+x+y-1)
J = F.derivative()
for i in [1..n]:
print "Iteración ",i,":"
print
Jxi = J(x0[0],x0[1])
Fxi = -F(x0[0],x0[1])
xd = Jxi.solve_right(Fxi)
#print "Aproximación de la solución del sistema lineal:"
x1 = x0 + xd
print "Aproximación de la solución del sistema No lineal:"
print x1
print
x0 = x1
Iteración 1 :

Aproximación de la solución del sistema No lineal:


(2.0, 0.0)

Iteración 2 :

Aproximación de la solución del sistema No lineal:


(0.5, 0.5)

Iteración 3 :
       
Aproximación de la solución del sistema No lineal:
(0.21666666666666667, 0.5166666666666667)

Iteración 4 :

Aproximación de la solución del sistema No lineal:


(0.21975572957824802, 0.5150108433768179)

Iteración 5 :

Aproximación de la solución del sistema No lineal:


(0.21975640380642225, 0.5150091606465478)

https://sage-cum.unex.es:8015/home/GIT21dgilpare/13/ 31/31

También podría gustarte