{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Factorización de matrices\n", "#### https://meet.noysi.com/metodosnumericos1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Veamos algunas funciones de Sage para resolver sistemas lineales." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrr}\n", "1.0 & 2.0 & 1.0 \\\\\n", "3.0 & 2.0 & 1.0 \\\\\n", "2.0 & 4.0 & 4.0\n", "\\end{array}\\right)$$" ], "text/plain": [ "[1.0 2.0 1.0]\n", "[3.0 2.0 1.0]\n", "[2.0 4.0 4.0]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Definimos una matrix de números en doble precisión\n", "A = matrix(RDF,[[1,2,1],[3,2,1],[2,4,4]])\n", "show(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos calcular una factorización de Schur" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrr}\n", "0.30080722495605444 & 0.5333732643197461 & -0.790587107359547 \\\\\n", "0.39331621941084755 & -0.8245806870099741 & -0.40665592600934425 \\\\\n", "0.8688022588383368 & 0.18862569156680933 & 0.45782418406889225\n", "\\end{array}\\right) \\left(\\begin{array}{rrr}\n", "6.5033076346549805 & -1.507281212000403 & -2.6133261715360243 \\\\\n", "0.0 & -0.8882360088434105 & 1.377907714295652 \\\\\n", "0.0 & 0.0 & 1.384928374188435\n", "\\end{array}\\right)$$" ], "text/plain": [ "[ 0.30080722495605444 0.5333732643197461 -0.790587107359547]\n", "[ 0.39331621941084755 -0.8245806870099741 -0.40665592600934425]\n", "[ 0.8688022588383368 0.18862569156680933 0.45782418406889225] [ 6.5033076346549805 -1.507281212000403 -2.6133261715360243]\n", "[ 0.0 -0.8882360088434105 1.377907714295652]\n", "[ 0.0 0.0 1.384928374188435]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "Q,T = A.schur()\n", "show(Q,T)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Comprobamos que es la factorización buscada" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrr}\n", "1.0000000000000024 & 2.0000000000000013 & 1.0000000000000013 \\\\\n", "3.0000000000000018 & 2.000000000000004 & 1.0000000000000033 \\\\\n", "2.0000000000000044 & 4.000000000000004 & 4.0000000000000036\n", "\\end{array}\\right) \\left(\\begin{array}{rrr}\n", "0.9999999999999999 & 3.695068889668288 \\times 10^{-16} & 2.0753696586837751 \\times 10^{-16} \\\\\n", "3.695068889668288 \\times 10^{-16} & 1.0000000000000002 & 2.8058042907128213 \\times 10^{-16} \\\\\n", "2.0753696586837751 \\times 10^{-16} & 2.8058042907128213 \\times 10^{-16} & 1.0000000000000004\n", "\\end{array}\\right)$$" ], "text/plain": [ "[1.0000000000000024 2.0000000000000013 1.0000000000000013]\n", "[3.0000000000000018 2.000000000000004 1.0000000000000033]\n", "[2.0000000000000044 4.000000000000004 4.0000000000000036] [ 0.9999999999999999 3.695068889668288e-16 2.0753696586837751e-16]\n", "[ 3.695068889668288e-16 1.0000000000000002 2.8058042907128213e-16]\n", "[2.0753696586837751e-16 2.8058042907128213e-16 1.0000000000000004]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show(Q*T*Q.conjugate_transpose(),Q*Q.conjugate_transpose())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "También una factorización LU (de Doolittle). \n", "**¡Ojo!** Sage no devuelve en la forma $PA=LU$, sino $A=PLU$." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrr}\n", "0.0 & 0.0 & 1.0 \\\\\n", "1.0 & 0.0 & 0.0 \\\\\n", "0.0 & 1.0 & 0.0\n", "\\end{array}\\right) \\left(\\begin{array}{rrr}\n", "1.0 & 0.0 & 0.0 \\\\\n", "0.6666666666666666 & 1.0 & 0.0 \\\\\n", "0.3333333333333333 & 0.5 & 1.0\n", "\\end{array}\\right) \\left(\\begin{array}{rrr}\n", "3.0 & 2.0 & 1.0 \\\\\n", "0.0 & 2.666666666666667 & 3.3333333333333335 \\\\\n", "0.0 & 0.0 & -1.0\n", "\\end{array}\\right) \\left(\\begin{array}{rrr}\n", "1.0 & 2.0 & 1.0 \\\\\n", "3.0 & 2.0 & 1.0 \\\\\n", "2.0 & 4.0 & 4.0\n", "\\end{array}\\right)$$" ], "text/plain": [ "[0.0 0.0 1.0]\n", "[1.0 0.0 0.0]\n", "[0.0 1.0 0.0] [ 1.0 0.0 0.0]\n", "[0.6666666666666666 1.0 0.0]\n", "[0.3333333333333333 0.5 1.0] [ 3.0 2.0 1.0]\n", "[ 0.0 2.666666666666667 3.3333333333333335]\n", "[ 0.0 0.0 -1.0] [1.0 2.0 1.0]\n", "[3.0 2.0 1.0]\n", "[2.0 4.0 4.0]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "P,L,U = A.LU()\n", "show(P,L,U,P*L*U)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrr}\n", "1 & 2 & 1 \\\\\n", "3 & 2 & 1 \\\\\n", "2 & 4 & 4\n", "\\end{array}\\right)$$" ], "text/plain": [ "[1 2 1]\n", "[3 2 1]\n", "[2 4 4]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Definimos una matrix de números enteros\n", "A = matrix([[1,2,1],[3,2,1],[2,4,4]])\n", "show(A)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(\n", "[1 0 0] [1 0 0] [ 1 2 1]\n", "[0 1 0] [3 1 0] [ 0 -4 -2]\n", "[0 0 1], [2 0 1], [ 0 0 2]\n", ")" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.LU(pivot='nonzero')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "También podemos resolver directamente el sistema $Ax = b$ usando la función *solve_right* (usa eliminación gaussiana)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(0.5, 0.0, 0.5)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "b = vector(RDF,[1,2,3])\n", "A.solve_right(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Otra manera de denotarlo es con el operador \"\\\\\"." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(0.5, 0.0, 0.5)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A\\b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para medir el tiempo que tarda en realizar una operación, usaremos la función *time* de la librería *time*. Para ello, primero cargamos la librería, después guardamos el tiempo inicial, ponemos nuestro código y guardamos el tiempo final. " ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.001966238021850586" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import time\n", "st = time.time() # Tiempo inicial \n", "\n", "# Código\n", "factorial(10000)\n", "\n", "et = time.time() # Tiempo final\n", "et - st # Diferencia" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vamos a calcular cuánto tiempo tarda en resolver un sistema de 100x100" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "# Generamos una matriz aleatoria de 100x100\n", "A = matrix.random(RDF,100,100)\n", "# Generamos un vector aleatorio de 100 elementos\n", "b = vector([random() for k in range(100)])" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.6576704978942871" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import time\n", "st = time.time() # Tiempo inicial \n", "\n", "# Resolvemos el sistema, pero no lo mostramos (para no calcular ese tiempo)\n", "for _ in range(1000):\n", " xs = A\\b\n", "\n", "et = time.time() # Tiempo final\n", "et - st # Tiempo que ha tardado" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " Ejercicio 1. \n", "Consideremos la matriz:\n", "$$\n", "A=\\left(\\begin{array}{rrr}\n", "1 & 2 & 1 \\\\\n", "3 & 2 & 1 \\\\\n", "-2 & -4 & 4\n", "\\end{array}\\right)$$\n", " \n", "**a)** Obtener la factorización de Schur. ¿Qué ocurre? Calcular los autovalores de la matriz $A$ y discutir porqué no factoriza en los reales como una matriz unitaria por una matriz triangular por la transpuesta de la unitaria. Obtener la factorización en los números complejos en doble precisión (CDF)\n", "\n", "**b)** Resolver el sistema $Ax=b$ con $b=(1,2,3)$ usando la factorización anterior.\n", "\n", "**c)** Consideremos ahora la aplicación lineal dada por\n", "$$A=\\left(\\begin{array}{rrr}\n", "4 & 2 & -2 \\\\\n", "2 & 2 & -4 \\\\\n", "-2 & -4 & 11 \\\\\n", "\\end{array}\\right)$$\n", "Calcular su factorización de Schur. Deducir que la matriz es definida positiva. Representar las columnas de la matriz $U$ y también las de $A U$. Comprobar que en ambos casos son vectores ortogonales.\n", "\n", "d) Obtener la factorización de Schur de cualquiera de las matrices anteriores \"paso a paso\", siguiendo la demostración vista en clase. Para calcular un autovector se puede usar la función eigenvectors_right y para extender a una base ortonormal, se puede utilizar la función gram_schmidt de Sage. \n", "
" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrr}\n", "1.0 & 2.0 & 1.0 \\\\\n", "3.0 & 2.0 & 1.0 \\\\\n", "-2.0 & -4.0 & 4.0\n", "\\end{array}\\right)$$" ], "text/plain": [ "[ 1.0 2.0 1.0]\n", "[ 3.0 2.0 1.0]\n", "[-2.0 -4.0 4.0]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "A = matrix(RDF,[[1,2,1],[3,2,1],[-2,-4,4]])\n", "show(A)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrr}\n", "-0.7318717503574348 & -0.16272623270313655 & 0.6617279759984384 \\\\\n", "0.6448378884837489 & 0.14860231667063856 & 0.7497342522893958 \\\\\n", "0.22033574064269745 & -0.9754165903194197 & 0.0038257973117043517\n", "\\end{array}\\right) \\left(\\begin{array}{rrr}\n", "-1.0632187495592365 & -1.0556113258123003 & -0.28402152320817975 \\\\\n", "0.0 & 4.031609374779613 & 4.3672968471306906 \\\\\n", "0.0 & -1.446911310750419 & 4.031609374779613\n", "\\end{array}\\right)$$" ], "text/plain": [ "[ -0.7318717503574348 -0.16272623270313655 0.6617279759984384]\n", "[ 0.6448378884837489 0.14860231667063856 0.7497342522893958]\n", "[ 0.22033574064269745 -0.9754165903194197 0.0038257973117043517] [ -1.0632187495592365 -1.0556113258123003 -0.28402152320817975]\n", "[ 0.0 4.031609374779613 4.3672968471306906]\n", "[ 0.0 -1.446911310750419 4.031609374779613]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "U,T = A.schur()\n", "show(U,T)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[-1.0632187495592365,\n", " 4.031609374779613 + 2.513780261979563*I,\n", " 4.031609374779613 - 2.513780261979563*I]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.eigenvalues()" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrr}\n", "-0.16326281165717438 - 0.7134294031654766i & 0.073314581774857 - 0.3514056536231743i & -0.1862689791099512 - 0.5484584279149419i \\\\\n", "0.1438476709690138 + 0.6285886969879189i & -0.19987247529089774 - 0.3413525405421148i & -0.047826679390865635 - 0.6522469953942274i \\\\\n", "0.04915155217881312 + 0.21478352712202906i & 0.828473018904845 - 0.16822880946518373i & -0.47874461274058144 + 0.08710500433341252i\n", "\\end{array}\\right) \\left(\\begin{array}{rrr}\n", "-1.0632187495592367 - 1.5543122344752192 \\times 10^{-15}i & 0.1662339788407182 - 0.9107416535654272i & 0.22587781290104247 + 0.5356105069987256i \\\\\n", "0.0 & 4.031609374779618 + 2.5137802619795653i & -0.03296300892499042 + 2.920199500229686i \\\\\n", "0.0 & 0.0 & 4.031609374779616 - 2.513780261979565i\n", "\\end{array}\\right)$$" ], "text/plain": [ "[ -0.16326281165717438 - 0.7134294031654766*I 0.073314581774857 - 0.3514056536231743*I -0.1862689791099512 - 0.5484584279149419*I]\n", "[ 0.1438476709690138 + 0.6285886969879189*I -0.19987247529089774 - 0.3413525405421148*I -0.047826679390865635 - 0.6522469953942274*I]\n", "[ 0.04915155217881312 + 0.21478352712202906*I 0.828473018904845 - 0.16822880946518373*I -0.47874461274058144 + 0.08710500433341252*I] [-1.0632187495592367 - 1.5543122344752192e-15*I 0.1662339788407182 - 0.9107416535654272*I 0.22587781290104247 + 0.5356105069987256*I]\n", "[ 0.0 4.031609374779618 + 2.5137802619795653*I -0.03296300892499042 + 2.920199500229686*I]\n", "[ 0.0 0.0 4.031609374779616 - 2.513780261979565*I]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "A = matrix(CDF,[[1,2,1],[3,2,1],[-2,-4,4]])\n", "U,T = A.schur()\n", "show(U,T)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6.28263140134084e-16" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(U*U.conjugate_transpose() - matrix.identity(3)).norm(oo)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "b = vector([1,2,3])" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(0.49999999999999967 + 2.7755575615628914e-17*I, -0.16666666666666635 + 2.220446049250313e-16*I, 0.8333333333333335 + 1.6653345369377348e-16*I)" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# (U*)*y = b\n", "y = U.conjugate_transpose()*b\n", "# T*z = y\n", "z = T.solve_right(y) # T\\y \n", "# U*x = z\n", "xs = U*z\n", "xs" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "A = matrix(RDF,[[4,2,-2],[2,2,-4],[-2,-4,11]])" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "U,T = A.schur()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plot(U.column(0)) + plot(U.column(1)) + plot(U.column(2))" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plot((A*U).column(0).normalized()) + plot((A*U).column(1).normalized()) + plot((A*U).column(2).normalized())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " Ejercicio 2. \n", " \n", "**a)** Obtener la factorización LU con pivote de la matriz \n", "$$\n", "A=\\left(\\begin{array}{rrr}\n", "1 & 2 & 1 \\\\\n", "3 & 2 & 1 \\\\\n", "3 & -4 & 4\n", "\\end{array}\\right)$$\n", "\n", "**b)** Utilizar dicha factorización para obtener la inversa de $A$.\n", "\n", "c) Obtener la factorización LU con pivote de $A^tA$. A partir de dicha factorización, obtener la factorización de la forma $L D L^t$ y a partir de ella la factorización de Choleski. \n", "\n", "d) Representar en una gráfica el tiempo de ejecución de la resolución de los sistemas lineales generados aleatoriamente para matrices de tamaño hasta 1000x1000. Debería ser aproximadamente la gráfica de una función cúbica. \n", "
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "SageMath 9.5", "language": "sage", "name": "sagemath" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.2" } }, "nbformat": 4, "nbformat_minor": 4 }