{ "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": 9, "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": 10, "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": 11, "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": 12, "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": 13, "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": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Definimos una matrix de números enteros\n", "B = matrix([[1,2,1],[3,2,1],[2,4,4]])\n", "B.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": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(0.5, 0.0, 0.5)" ] }, "execution_count": 14, "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": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(0.5, 0.0, 0.5)" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A\\b" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1.0, 2.0, 3.0)" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Comprobamos\n", "A*(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": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.0013327598571777344" ] }, "execution_count": 21, "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": 22, "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": 27, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.6425516605377197" ] }, "execution_count": 27, "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": [ "