Métodos Numéricos Tema 7: Valores y vectores propios Practica 1 Prof: Francisco Palacios EPSEM-UPC Curso 2006/2007 Versión 1.1 Contenido · Polinomio característco. · Cálculo de valores propios con solve y fsolve. · Cálculo de valores propios con el comando eigenvals. · Comando eigenvects. · Diagonalización. · Programa para método de la potencia. · Programa para método de la potencia. Parada por error estimado sobre el valor propio. · Mètodo de la potencia inversa. · Mètodo de la potencia desplazada. > restart; 1. Polinomio característico Cálculo "manual" del polinomio caracterísco. p(t)=det(A-t*I). > with(linalg): Warning, new definition for norm Warning, new definition for trace > a:=matrix(3,3,[1,2,1,0,1,2,1,3,2]); ⎡1 ⎢ a := ⎢ 0 ⎢ ⎣1 2 1 3 1⎤ ⎥ 2⎥ ⎥ 2⎦ Construimos la matriz unitaria de orden 3. > id3:=diag(1,1,1); ⎡1 ⎢ id3 := ⎢ 0 ⎢ ⎣0 0 1 0 0⎤ ⎥ 0⎥ ⎥ 1⎦ > b:=evalm(a-t*id3); ⎡1 − t ⎢ b := ⎢ 0 ⎢ ⎣ 1 2 1−t 3 1 ⎤ ⎥ 2 ⎥ ⎥ 2 − t⎦ > p:=det(b); p := −1 + 2 t + 4 t2 − t3 Cálculo directo del polinomio característico usando charpoly. > p1:=charpoly(a,t); p1 := −2 t − 4 t2 + t3 + 1 p y p1 pueden ser distintos en un cambio de signo, Maple calcula el polinomio característico de una matriz de orden n como p(t)=(-1)^n det(A-tI). 2. Cálculo de vaps con solve y fsolve C alculamos las raíces del polinomio característico con solve. > vaps:=solve(p); vaps := − 1 6 %11 / 3 + 1 12 44 %11 / 3 − 1 3 %1 1/3 22 1 3 %1 %1 := 692 + 12 I > evalf(vaps); 4 1 22 1 4 1 %11 / 3 − + + I + ,− 1/3 3 12 3 %1 3 2 1/3 + 4 3 − 1 2 I 44 1 ⎞ ⎛1 ⎟, 3 ⎜⎜ %11 / 3 − 3 %11 / 3 ⎟⎠ ⎝6 44 1 ⎞ ⎛1 ⎟ 3 ⎜⎜ %11 / 3 − 3 %11 / 3 ⎟⎠ ⎝6 1407 -9 -9 4.402678830, −.7187096905 − .9 10 Page 1 I, .3160308605 + .9 10 I En la evaluació float aparecen partes complejas "residuales". Es preferible usar fsolve si sabemos que los valores propios son reales. > vaps:=fsolve(p); vaps := -.7187096904, .3160308609, 4.402678830 3. Comando eigenvals El comando eigenvals proporciona directamente los valores propios. > a:=matrix(3,3,[1,2,1,0,1,2,1,3,2]); ⎡1 ⎢ a := ⎢ 0 ⎢ ⎣1 2 1 3 1⎤ ⎥ 2⎥ ⎥ 2⎦ > vaps:=eigenvals(a); vaps := − 1 6 %11 / 3 + 1 12 44 %11 / 3 − 1 3 %1 1/3 22 1 4 1 22 1 4 1 + ,− %11 / 3 − + + I 1 / 3 3 12 3 %1 3 2 3 %11 / 3 %1 := 692 + 12 I > evalf(vaps); + 4 3 − 1 2 I 44 1 ⎞ ⎛1 ⎟, 3 ⎜⎜ %11 / 3 − 3 %11 / 3 ⎟⎠ ⎝6 44 1 ⎞ ⎛1 ⎟ 3 ⎜⎜ %11 / 3 − 3 %11 / 3 ⎟⎠ ⎝6 1407 .3160308609, 4.402678830, -.7187096904 Si usamos una matriz "float", se obtienen valores aproximados para los valores propios. > af:=evalf(evalm(a)); ⎡1. ⎢ af := ⎢ 0 ⎢ ⎣1. 2. 1. 3. 1.⎤ ⎥ 2.⎥ ⎥ 2.⎦ > vaps:=eigenvals(af); vaps := .3160308609, 4.402678830, -.7187096904 4. Comando eigenvects El comando eigenvects proporciona los valores propios, multipliciad y vectores propios asociados. > a:=matrix(3,3,[1,2,1,0,1,2,1,3,2]); af:=evalf(evalm(a)); ⎡1 ⎢ a := ⎢ 0 ⎢ ⎣1 2 1 3 1⎤ ⎥ 2⎥ ⎥ 2⎦ ⎡1. ⎢ af := ⎢ 0 ⎢ ⎣1. 2. 1. 3. 1.⎤ ⎥ 2.⎥ ⎥ 2.⎦ > veps:=eigenvects(af); veps := [ 4.402678829, 1, { [ -.5201207449, -.4781522694, -.8134993026 ] } ], [ -.7187096906, 1, { [ -.6779459756, 1.021520419, -.8778485199 ] } ], [ .3160308632, 1, { [ -.916668609, .3781466858, -.1293203316 ] } ] Podemos acceder al contenido de la estructura compleja veps usando ínices. veps[1,3] es el tercer elemento del primer objeto en veps. > veps[1,3]; { [ -.5201207449, -.4781522694, -.8134993026 ] } > veps[1,3,1]; [ -.5201207449, -.4781522694, -.8134993026 ] Construcción de una matriz que tiene en columnas los vectores propios. > v1:=veps[1,3,1]; v1 := [ -.5201207449, -.4781522694, -.8134993026 ] > v2:=veps[2,3,1]; v2 := [ -.6779459756, 1.021520419, -.8778485199 ] > v3:=veps[3,3,1]; v3 := [ -.916668609Page , .3781466858 , -.1293203316 ] 2 > v:=transpose(matrix([v1,v2,v3])); ⎡-.5201207449 ⎢ v := ⎢-.4781522694 ⎢ ⎣-.8134993026 -.6779459756 1.021520419 -.8778485199 -.916668609 ⎤ ⎥ .3781466858 ⎥ ⎥ -.1293203316⎦ 5. Diagonalización Si las columnas de V son una base de vectores propios de la matriz A, entonces el producto D=inv(V) A V es una matriz diagonal. > d:=evalm(inverse(v)&*a&*v); ⎡4.402678827 -.8 10-9 ⎤⎥ -.5 10-8 ⎢ -8 ⎢ d := ⎢ .19 10 -.7187096905 -.36 10-9 ⎥⎥ ⎢ ⎥ -7 -8 .33 10 .3160308607⎦ ⎣ -.102 10 Observa que hay elementos residuales que no son exactamente cero. el sugiente programa sirve para filtrar los elementos casi nulos. > filt0:=x->if abs(x)<10^(-6) then 0 else x fi; filt0 := proc(x) option operator, arrow; if abs( x ) < 1 / 1000000 then 0 else x fi end Aplicamos el programa a la matriz usando el comando map > df:=map(filt0,d); ⎡4.402678827 ⎢ df := ⎢ 0 ⎢ ⎣ 0 0 -.7187096905 0 0 ⎤ ⎥ ⎥ 0 ⎥ .3160308607⎦ 6. Progama para método de la potencia El método de la potencia permite determinar el valor propio de módulo máximo y un vector propio asociado. > with(linalg): a:=matrix(3,3,[1,2,1,0,1,2,1,3,2]); x0:=[1,1,1];# vector inicial n:=3; for i from 0 to n do `********** iteración`,i+1,`**********`; y.(i+1):=evalf(evalm(a&*x.i)); ny:=norm(y.(i+1), infinity); for j from 1 to vectdim(x0) do if abs(y.(i+1)[j])=ny then cdom:=y.(i+1)[j];break;fi; od; c.(i+1):=cdom; x.(i+1):=evalm(y.(i+1)/c.(i+1)); od; ⎡1 ⎢ a := ⎢ 0 ⎢ ⎣1 2 1 3 1⎤ ⎥ 2⎥ ⎥ 2⎦ x0 := [ 1, 1, 1 ] n := 3 ********** iteración, 1, ********** y1 := [ 4., 3., 6. ] ny := 6. c1 := 6. x1 := [ .6666666668, .5000000001, 1.000000000 ] ********** iteración, 2, ********** y2 := [ 2.666666667, 2.500000000, 4.166666667 ] ny := 4.166666667 c2 := 4.166666667 x2 := [ .6400000001, .6000000000, 1.000000000 ] ********** iteración, 3, ********** y3 := [ 2.840000000, 2.600000000, 4.440000000 ] ny := 4.440000000 c3 := 4.440000000 Page 3 x3 := [ .6396396396, .5855855855, .9999999999 ] ********** iteración, 4, ********** y4 := [ 2.810810811, 2.585585586, 4.396396397 ] ny := 4.396396397 c4 := 4.396396397 x4 := [ .6393442624, .5881147542, 1.000000000 ] 7. Programa con parada por error estimado sobre el valor propio > with(linalg): a:=matrix(3,3,[1,2,1,0,1,2,1,3,2]); x0:=[1,1,1]; t:=3; n:=14; c0:=10^(10); for i from 0 to n do `********** iteración`,i+1,`**********`; y.(i+1):=evalf(evalm(a&*x.i)); ny:=norm(y.(i+1), infinity); for j from 1 to vectdim(x0) do if abs(y.(i+1)[j])=ny then cdom:=y.(i+1)[j];break;fi; od; c.(i+1):=cdom; x.(i+1):=evalm(y.(i+1)/c.(i+1)); er.(i+1):=c.(i+1)-c.i; if abs(er.(i+1))<0.5*10^(-t) then print(`*** precisión alcazada ***`);break; fi; od; ⎡1 ⎢ a := ⎢ 0 ⎢ ⎣1 2 1 3 1⎤ ⎥ 2⎥ ⎥ 2⎦ x0 := [ 1, 1, 1 ] t := 3 n := 14 c0 := 10000000000 ********** iteración, 1, ********** y1 := [ 4., 3., 6. ] ny := 6. c1 := 6. x1 := [ .6666666668, .5000000001, 1.000000000 ] er1 := -.9999999994 1010 ********** iteración, 2, ********** y2 := [ 2.666666667, 2.500000000, 4.166666667 ] ny := 4.166666667 c2 := 4.166666667 x2 := [ .6400000001, .6000000000, 1.000000000 ] er2 := -1.833333333 ********** iteración, 3, ********** y3 := [ 2.840000000, 2.600000000, 4.440000000 ] ny := 4.440000000 c3 := 4.440000000 x3 := [ .6396396396, .5855855855, .9999999999 ] er3 := .273333333 ********** iteración, 4, ********** y4 := [ 2.810810811, 2.585585586, 4.396396397 ] Page 4 ny := 4.396396397 c4 := 4.396396397 x4 := [ .6393442624, .5881147542, 1.000000000 ] er4 := -.043603603 ********** iteración, 5, ********** y5 := [ 2.815573770, 2.588114754, 4.403688525 ] ny := 4.403688525 c5 := 4.403688525 x5 := [ .6393671474, .5877152164, 1.000000000 ] er5 := .007292128 ********** iteración, 6, ********** y6 := [ 2.814797580, 2.587715216, 4.402512796 ] ny := 4.402512796 c6 := 4.402512796 x6 := [ .6393615898, .5877814185, 1.000000000 ] er6 := -.001175729 ********** iteración, 7, ********** y7 := [ 2.814924427, 2.587781419, 4.402705846 ] ny := 4.402705846 c7 := 4.402705846 x7 := [ .6393623661, .5877706823, 1.000000000 ] er7 := .000193050 *** precisión alcazada *** > af:=evalf(evalm(a)); eigenvals(af); ⎡1. ⎢ af := ⎢ 0 ⎢ ⎣1. 2. 1. 3. 1.⎤ ⎥ 2.⎥ ⎥ 2.⎦ .3160308609, 4.402678830, -.7187096904 8. Método de la potencia inversa Calcula el valor propio de módulo mínimo. > with(linalg): a:=matrix(3,3,[1,2,1,0,1,2,1,3,2]); af:=evalf(evalm(a)); a1:=inverse(af); x0:=[1,2,1]; t:=3; n:=24; c0:=10^(10); for i from 0 to n do `********** iteración`,i+1,`**********`; y.(i+1):=evalf(evalm(a1&*x.i)); ny:=norm(y.(i+1), infinity); for j from 1 to vectdim(x0) do if abs(y.(i+1)[j])=ny then cdom:=y.(i+1)[j];break;fi; od; c.(i+1):=cdom; x.(i+1):=evalm(y.(i+1)/c.(i+1)); er.(i+1):=c.(i+1)-c.i; if abs(er.(i+1))<0.5*10^(-t) then print(`*** precisión alcazada ***`); vapdom_a1:=c.(i+1); break; fi; od; vap_min:=1/vapdom_a1; Page 5 ⎡1 ⎢ a := ⎢ 0 ⎢ ⎣1 2 1 3 1⎤ ⎥ 2⎥ ⎥ 2⎦ ⎡1. ⎢ af := ⎢ 0 ⎢ ⎣1. 2. 1. 3. 1.⎤ ⎥ 2.⎥ ⎥ 2.⎦ ⎡ 4.000000000 ⎢ a1 := ⎢-2.000000000 ⎢ ⎣ 1.000000000 1.000000000 -1.000000000 1.000000000 -3.000000000⎤ ⎥ 2.000000000 ⎥ ⎥ -1.000000000⎦ x0 := [ 1, 2, 1 ] t := 3 n := 24 c0 := 10000000000 ********** iteración, 1, ********** y1 := [ 3.000000000, -2.000000000, 2.000000000 ] ny := 3.000000000 c1 := 3.000000000 x1 := [ .9999999999, -.6666666666, .6666666666 ] er1 := -.9999999997 1010 ********** iteración, 2, ********** y2 := [ 1.333333333, 0, -.3333333333 ] ny := 1.333333333 c2 := 1.333333333 x2 := [ 1.000000000, 0, -.2500000000 ] er2 := -1.666666667 ********** iteración, 3, ********** y3 := [ 4.750000000, -2.500000000, 1.250000000 ] ny := 4.750000000 c3 := 4.750000000 x3 := [ 1.000000000, -.5263157895, .2631578948 ] er3 := 3.416666667 ********** iteración, 4, ********** y4 := [ 2.684210527, -.9473684214, .2105263157 ] ny := 2.684210527 c4 := 2.684210527 x4 := [ 1.000000000, -.3529411765, .07843137249 ] er4 := -2.065789473 ********** iteración, 5, ********** y5 := [ 3.411764707, -1.490196079, .5686274510 ] ny := 3.411764707 c5 := 3.411764707 x5 := [ 1.000000000, -.4367816092, .1666666666 ] er5 := .727554180 ********** iteración, 6, ********** y6 := [ 3.063218391, -1.229885058, .3965517242 ] ny := 3.063218391 c6 := 3.063218391 x6 := [ 1.000000000, -.4015009383, .1294559100 ] er6 := -.348546316 ********** iteración, 7, ********** y7 := [ 3.210131332, -1.339587242, .4690431517 ] ny := 3.210131332 c7 := 3.210131332 Page 6 x7 := [ 1.000000000, -.4172998247, .1461133839 ] er7 := .146912941 ********** iteración, 8, ********** y8 := [ 3.144360023, -1.290473407, .4365867914 ] ny := 3.144360023 c8 := 3.144360023 x8 := [ 1.000000000, -.4104089218, .1388475837 ] er8 := -.065771309 ********** iteración, 9, ********** y9 := [ 3.173048327, -1.311895911, .4507434945 ] ny := 3.173048327 c9 := 3.173048327 x9 := [ 1.000000000, -.4134497102, .1420537755 ] er9 := .028688304 ********** iteración, 10, ********** y10 := [ 3.160388964, -1.302442739, .4444965143 ] ny := 3.160388964 c10 := 3.160388964 x10 := [ 1.000000000, -.4121146966, .1406461418 ] er10 := -.012659363 ********** iteración, 11, ********** y11 := [ 3.165946878, -1.306593019, .4472391616 ] ny := 3.165946878 c11 := 3.165946878 x11 := [ 1.000000000, -.4127021297, .1412655294 ] er11 := .005557914 ********** iteración, 12, ********** y12 := [ 3.163501282, -1.304766811, .4460323409 ] ny := 3.163501282 c12 := 3.163501282 x12 := [ 1.000000000, -.4124439015, .1409932544 ] er12 := -.002445596 ********** iteración, 13, ********** y13 := [ 3.164576336, -1.305569590, .4465628441 ] ny := 3.164576336 c13 := 3.164576336 x13 := [ 1.000000000, -.4125574647, .1411129948 ] er13 := .001075054 ********** iteración, 14, ********** y14 := [ 3.164103551, -1.305216545, .4463295405 ] ny := 3.164103551 c14 := 3.164103551 x14 := [ 1.000000000, -.4125075314, .1410603456 ] er14 := -.000472785 *** precisión alcazada *** vap_min := .3160452823 > eigenvals(af); .3160308609, 4.402678830, -.7187096904 9. Método de la potencia desplazada Calcula un valor propio próximo a un valor dado. > with(linalg): Page 7 a:=matrix(3,3,[1,2,1,0,1,2,1,3,2]); af:=evalf(evalm(a)); vapest:=-0.5;# Estimacion del valor propio id3:=diag(1,1,1); b:=evalm(af-vapest*id3); b1:=inverse(b); x0:=[1,2,1]; t:=3; n:=14; c0:=10^(10); for i from 0 to n do `********** iteración`,i+1,`**********`; y.(i+1):=evalf(evalm(b1&*x.i)); ny:=norm(y.(i+1), infinity); for j from 1 to vectdim(x0) do if abs(y.(i+1)[j])=ny then cdom:=y.(i+1)[j];break;fi; od; c.(i+1):=cdom; x.(i+1):=evalm(y.(i+1)/c.(i+1)); er.(i+1):=c.(i+1)-c.i; if abs(er.(i+1))<0.5*10^(-t) then print(`*** precisión alcazada ***`); vap_dom_desp:=c.(i+1); break; fi; od; vap:=1/c.(i+1)+vapest; ⎡1 ⎢ a := ⎢ 0 ⎢ ⎣1 2 1 3 1⎤ ⎥ 2⎥ ⎥ 2⎦ ⎡1. ⎢ af := ⎢ 0 ⎢ ⎣1. 2. 1. 3. 1.⎤ ⎥ 2.⎥ ⎥ 2.⎦ vapest := -.5 ⎡1.5 ⎢ b := ⎢ 0 ⎢ ⎣ 1. ⎡ 2.571428571 ⎢ b1 := ⎢-2.285714286 ⎢ ⎣ 1.714285714 2. 1.5 3. 1. ⎤ ⎥ 2. ⎥ ⎥ 2.5⎦ 2.285714286 -3.142857143 2.857142857 -2.857142857⎤ ⎥ 3.428571429 ⎥ ⎥ -2.571428571⎦ x0 := [ 1, 2, 1 ] t := 3 n := 14 c0 := 10000000000 ********** iteración, 1, ********** y1 := [ 4.285714286, -5.142857143, 4.857142857 ] ny := 5.142857143 c1 := -5.142857143 x1 := [ -.8333333332, .9999999998, -.9444444442 ] er1 := -.1000000001 1011 ********** iteración, 2, ********** y2 := [ 2.841269842, -4.476190475, 3.857142856 ] ny := 4.476190475 c2 := -4.476190475 x2 := [ -.6347517734, 1.000000000, -.8617021277 ] er2 := .666666668 ********** iteración, 3, ********** y3 := [ 3.115501519Page , -4.646403241 , 3.984802431 ] 8 ny := 4.646403241 c3 := -4.646403241 x3 := [ -.6705189709, 1.000000000, -.8576101180 ] er3 := -.170212766 ********** iteración, 4, ********** y4 := [ 3.011837270, -4.550619900, 3.912964924 ] ny := 4.550619900 c4 := -4.550619900 x4 := [ -.6618520852, .9999999999, -.8598751400 ] er4 := .095783341 ********** iteración, 5, ********** y5 := [ 3.040595038, -4.578195715, 3.933646785 ] ny := 4.578195715 c5 := -4.578195715 x5 := [ -.6641470195, 1.000000000, -.8592133300 ] er5 := -.027575815 ********** iteración, 6, ********** y6 := [ 3.032802893, -4.570681088, 3.928010814 ] ny := 4.570681088 c6 := -4.570681088 x6 := [ -.6635341286, 1.000000000, -.8593928866 ] er6 := .007514627 ********** iteración, 7, ********** y7 := [ 3.034891917, -4.572697603, 3.929523202 ] ny := 4.572697603 c7 := -4.572697603 x7 := [ -.6636983637, 1.000000000, -.8593446458 ] er7 := -.002016515 ********** iteración, 8, ********** y8 := [ 3.034331767, -4.572156811, 3.929117609 ] ny := 4.572156811 c8 := -4.572156811 x8 := [ -.6636543521, .9999999998, -.8593575790 ] er8 := .000540792 ********** iteración, 9, ********** y9 := [ 3.034481892, -4.572301751, 3.929226312 ] ny := 4.572301751 c9 := -4.572301751 x9 := [ -.6636661484, 1.000000000, -.8593541123 ] er9 := -.000144940 *** precisión alcazada *** vap := -.7187082250 > eigenvals(af); .3160308609, 4.402678830, -.7187096904 > Page 9