{ "cells": [ { "cell_type": "markdown", "metadata": { "internals": { "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "# Matrix Operations" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "hide_input": true }, "outputs": [], "source": [ "# for QR codes use inline\n", "%matplotlib inline\n", "qr_setting = 'url'\n", "#\n", "# for lecture use notebook\n", "# %matplotlib notebook\n", "# qr_setting = None\n", "#\n", "%config InlineBackend.figure_format='retina'\n", "# import libraries\n", "import numpy as np\n", "import matplotlib as mp\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "import laUtilities as ut\n", "import slideUtilities as sl\n", "import demoUtilities as dm\n", "import pandas as pd\n", "from importlib import reload\n", "from datetime import datetime\n", "from IPython.display import Image\n", "from IPython.display import display_html\n", "from IPython.display import display\n", "from IPython.display import Math\n", "from IPython.display import Latex\n", "from IPython.display import HTML;" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Today we will talk about multiplying matrices:\n", "* How do you multiply matrices?\n", "* What does the product of two matrices mean?\n", "* What algebraic rules apply to matrix multiplication?\n", "* What is the computational cost of matrix multiplication?" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "\"Arthur" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "Early in his life, Arthur Cayley practiced law to support his passion for mathematics. During his time as a practicing lawyer, he published over 200 papers on mathematics. Finally at the age of 42 he got a position at Cambridge University and took a big pay cut so he could become a full-time mathematician. He said he never regretted the choice. Cayley often said, “I love my subject.”\n", "\n", "In the mid 19th century mathematics was making enormous progress, but strangely the ideas of linear algebra had not been developed much. As I mentioned in the first lecture, people had been solving linear systems since ancient Chinese times (although “Nine Chapters on Arithmetic” was destroyed along with most technical books in China by Emperor Shih Hoang-ti in 213 BC). However it took Cayley to have the idea of extracting the coefficients as a separate entity called a matrix, worthy of independent study. He is the founder of linear algebra.\n", "\n", "In 1855-1857 Cayley formed the theory of matrices, and came up with a way to multiply matrices. As we’ll see, it is not the most obvious thing to do, but it was quickly realized that it was the “right” way. Cayley came about this idea by first thinking about linear transformations, and how to compose linear transformations. So that’s where we’ll start.\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Composing Linear Transformations" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "hide_input": false, "internals": { "frag_helper": "fragment_end", "frag_number": 5 }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/latex": [ "Reflection through the origin" ], "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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2YsgoUEJAAA+SUszZQVTp5r53LlSmzbxr3PttVJurjmljTxFLg49exE0nPgCAOAjL8odUlKkYcOkG2+UysXxJzs9exE0BF8AAHx02WXmQTdJ2rLFXGhRGujZiyAi+AIA4KPKlaWf/tSeO+3uEC969iKICL4AAPgs8jKLOXOclTvEg569CCqCLwAAPhswwA6eWVnS2rUl91n07EWQEXwBAPBZpUrSkCH2fM6ckvssevYiyAi+AAAkgMhyh4yMkil3oGcvgo7gCwBAArjkEqlmTTPevl364gtv16dnL0DwBQAgIaSmRtfael3uQM9egOALAEDCiLzMIiNDysvzZl169gIGwRcAgATRr59Uu7YZ79wprV7tzbr07AUMgi8AAAmiQgXpqqvsuReXWdCzF7ARfAEASCBeljvQsxeIRvAFACCB9O0r1a1rxtnZ0sqVzteiZy8QjeALAEACKV9euvpqe+603IGevcDpCL4AACSYyMss5s2TcnPj+3l69gIFI/gCAJBgevWSGjQw4z17pE8/je/n6dkLFIzgCwBAgklJka65xp7Hc5kFPXuBwhF8AQBIQJHdHebPl06diu3n6NkLFI7gCwBAArroIqlRIzPev1/65JPif4aevUDRCL4AACSglBTp2mvteXHlDvTsBYpH8AUAIEHlL3fIySn8vfTsBYpH8AUAIEF16yY1bWrGBw9Ky5YV/D569gKxIfgCAJCgypWLLnco6DILevYCsSP4AgCQwCLLHRYskE6ejP4+PXuB2BF8AQBIYF262GULhw9LH31kf4+evUB8CL4AACSwUCj61Dey3IGevUB8CL4AACS466+3x+++a8od6NkLxI/gCwBAgktPl84804yPHJEyM+nZCzhB8AUAIMHlL3cYOZKevYATBF8AAJJAZPCNRM9eIHYEXwAAkkDHjtJZZ53+Gj17gdgRfAEASAIFlTLQsxeID8EXAIAk0aFD9LxjR3/2ASQrgi8AAElixgypUycz3rZNqlDB3/0AyYa/IAEAIEmEQtKKFX7vAkhenPgCAAAgEAi+AAAACASCLwAAAAKB4AsAAIBAIPgCAAAgEAi+AAAACASCLwAAAAKB4AsAAIBAIPgCAAAgEAi+AAAACASCLwAAAAKB4AsAAIBAIPgCAAAgEAi+AAAACASCLwAAAAKB4AsAAIBAIPgCAAAgEAi+AAAACASC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\n", "text/plain": [ "
" ] }, "metadata": { "image/png": { "height": 350, "width": 351 }, "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "note = dm.mnote()\n", "A = np.array(\n", " [[-1, 0],\n", " [ 0,-1]])\n", "dm.plotSetup()\n", "dm.plotShape(note)\n", "dm.plotShape(A @ note,'r')\n", "Latex(r'Reflection through the origin')" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 5 }, "slideshow": { "slide_type": "-" } }, "source": [ "We determined that the matrix $C = \\left[\\begin{array}{rr}-1&0\\\\0&-1\\end{array}\\right]$ implements this linear transformation. " ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 7 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "But notice that we could have accomplished this another way:\n", "\n", "* First reflect through the $x_1$ axis \n", "* Then reflect through the $x_2$ axis" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 8 }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAr4AAAK8CAYAAAAJT7x+AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjMsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+AADFEAAAgAElEQVR4nOzdd5xU1f3/8ffsLgssSO9dYGmiIEgoUgVRUIPGGisak1hiIV/9hTTFRBNN9GuJJvkGDbbEIIiIShVYjTQVsNCV5lKX3tl6f38cd+/M1pl77+6d2ft6Ph48PGd29swxPAJvz37u54QsyxIAAABQ3SX5vQEAAACgKhB8AQAAEAgEXwAAAAQCwRcAAACBQPAFAABAIBB8AQAAEAgEXwAAAAQCwRcAAACBQPAFAABAIBB8AQAAEAgEXwAAAAQCwRcAAACBQPAFAABAIBB8AQAAEAgEXwCIQigUeiIUCi0MhUKZoVDoVCgUOhgKhVaHQqGHQ6FQY7/3BwCoWMiyLL/3AABxLxQK5UhaJWmdpCxJdSQNkHSepF2SBliWlenfDgEAFSH4AkAUQqFQLcuyTpfy+mOSfiXpb5Zl3VX1OwMARItSBwCIQmmh9ztvfvfP9KraCwDAGYIvALhz2Xf//NLXXQAAKkSpAwDEIBQKPSCprqT6MvW9g2VC7yjLsvb5uTcAQPkIvgAQg1AotEdS87CX5koab1nW3ii+d2UZX+ogaa5lWTe43yEAoCx+BV/SNoCEtnfvXi1dulQTJ07UsWPH9N5776lPnz7lfk/fvn1LfX39+vXq3r27Vq4sKxcDQCCFPF+Q4AsAzm3fvl1dunRRenq61qxZ42iNwkBM8AWACJ4HXx5uAwAX2rdvrx49emjt2rXav3+/39sBAJSD4AsALu3atUuSlJyc7PNOAADlIfgCQAU2bNigPXv2lHi9oKBAv/71r5WVlaVBgwapYcOGPuwOABCtFL83AADxbu7cuXrwwQc1dOhQderUSY0bN9bevXv14YcfasuWLWrRooUmT57s9zYBABUg+AJABUaNGqWf/OQnWrJkib744gsdPnxYderUUZcuXXTTTTfp3nvvVaNGjfzeJgCgAnR1AACf0dUBAEpFVwcAAADACYIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAAgEAg+AIAACAQCL4AAAAIBIIvAAAAAoHgCwAVOHDggF588UVdccUV6ty5s2rXrq369etr8ODBeumll1RQUOD3FgEAUUjxewMAEO+mTZumO++8Uy1bttSIESPUrl077d27VzNmzNDtt9+uOXPmaNq0aQqFQn5vFQBQjpBlWX58ri8fCgBOLFq0SCdOnNAll1yipCT7B2V79uzR9773PWVmZmr69Om68sorHa3ft29fSdLKlSs92S8AVBOenyZQ6gAAFbjgggt02WWXRYReSWrRooXuuOMOSVJGRoYPOwMAxILgCwAu1KhRQ5KUkkLlGADEO4IvADiUl5enV199VZJ08cUX+7wbAEBFOKIAAIcmTpyoNWvWaOzYsbrooosqfH9hLW9x69evV/fu3b3eHgCgGE58AcCB5557Tk899ZS6deum1157ze/tAACiwIkvAMTohRde0H333acePXpo4cKFatSoUVTfV1bXhrJOglGxggJp/34pM1PasUOqXVsaPlxKTfV7ZwDiEcEXAGLwzDPPaMKECerZs6cWLlyoZs2a+b2laqt4qC38Z/FxTk7k93XrJj33nHThhf7sG0D8IvgCQJSeeOIJTZw4Ub1799aCBQvUpEkTv7eU0CxLWrtW2rw5MsyWF2qjsWGDNHq0dMUV0v/+r9Shg+dbB5CgCL4AEIXf//73euihh9S3b1/Nnz8/6vIGlG7tWunOO6X//tf9WvXqSS1aSM2aSatXSydOmNfffluaM0eaOFH6f//PlEEACDZubgOACrzyyisaP368kpOTdc8996h+/fol3tOhQweNHz/e0fpBurnt5Enp0UelP/9Zysur+P2Fobb4r5YtpebNzbhOHfv9WVnSU09JM2dGrtOhgzn9vfxyiZulgYTh+f9bCb4AUIFJkybpkUceKfc9w4YNc3x7W1CC75w50t13S1u32q+lpEgDB0qtWpkg27KlCbOlhdpYrFol/f730rp1ka+PHi09+6ypAwYQ9wi+AFDdVPfgu3OndP/90vTpka/36SM98ojUpUvlfG5+vjRtmvT009Lhw/brKSlmP7/9rTlRBhC3PA++9PEFAFSK/HzTXaF798jQ26CBKXf4178qL/RKUnKydN110ty50g9/KCV99zdeXp705JNS167S66+bh+wABAPBFwDguc8+k/r3l+67Tzp2zH79iitMycPVV9tBtLI1bChNmiTNmGFOmQvt2SPddJM0ZIh5KA5A9UfwBQB45sgR6Z57pO99Twqv3OjYUXr1VenxxyW/GmJ07y79+9/mwbqmTe3XlyyRzjtPuusu6cABf/YGoGoQfAEArlmWqaft3l16/nm7fKBmTVNP+8475gTYb6GQ9P3vm/KHH/3I1PtK5rKMv/3NlF4sWeLvHgFUHoIvAMCVLVuksWOla66Rdu+2Xx88WHrvPdOvN96uEK5b1/T2nTXL7LPQwYPm34OTX6B6IvgCABz7+9+ls84yJ6iFmjY1nRRefFFq186/vUWjUyezzxdeMA/dSdKuXdJPf8pDb0B1RPAFADgyb545zT192sxDIemGG8zDa2PHJs5FEaGQNGqU9Ic/2K+99Zb08su+bQlAJSH4AgBilpUl3XKLPe/aVXrzTemhh6QzzvBvX26MHClde609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\n", "text/plain": [ "
" ] }, "metadata": { "image/png": { "height": 350, "width": 351 }, "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "A = np.array(\n", " [[ 1, 0],\n", " [ 0,-1]])\n", "B = np.array(\n", " [[-1, 0],\n", " [ 0, 1]])\n", "dm.plotSetup()\n", "dm.plotShape(note)\n", "dm.plotShape(A @ note,'g')\n", "dm.plotShape(B @ (A @ note),'r')" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 9 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "As we saw, to reflect a point through the $x_1$ axis, we multiply it by matrix $A = \\left[\\begin{array}{rr}1&0\\\\0&-1\\end{array}\\right]$.\n", "\n", "Likewise, to reflect a point through the $x_2$ axis, we multiply it by matrix $B = \\left[\\begin{array}{rr}-1&0\\\\0&1\\end{array}\\right]$." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 10 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "So, another way to reflect point ${\\bf u}$ through the origin would be:\n", "\n", "* ${\\bf v} = A{\\bf u}$\n", "* Followed by ${\\bf w} = B{\\bf v}.$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 11 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "In other words, ${\\bf w} = B(A{\\bf u}).$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 12, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "fragment" } }, "source": [ "But it is clear that $B(A{\\bf x})$ and $C{\\bf x}$ are the _same_ linear transformation. \n", "\n", "So, using $C$ we can go directly to the solution using one multiplication, rather than having to multiply twice (once for $A$ and once for $B$)." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 12, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "So a natural question is: given $A$ and $B$, could we find $C$ directly?\n", "\n", "In other words, for any $A$ and $B$, could we find $C$ such that:\n", "\n", "$$ A(B{\\bf x}) = C{\\bf x}? $$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 14 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "Let's determine how to find $C$ given $A$ and $B.$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 15 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "If $A$ is $m \\times n$, $B$ is $n \\times p$, and ${\\bf x} \\in \\mathbb{R}^p,$ denote the columns of $B$ by ${\\bf b_1},\\dots,{\\bf b_p},$ and the entries in ${\\bf x}$ by $x_1, \\dots, x_p.$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 16 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "Then:\n", "$$ B{\\bf x} = x_1{\\bf b_1} + \\dots + x_p {\\bf b_p}. $$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 17 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "and:\n", "\n", "$$A(B{\\bf x}) = A(x_1{\\bf b_1} + \\dots + x_p {\\bf b_p})$$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 18 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "Since matrix-vector multiplication is a linear transformation:\n", "\n", "$$ = x_1A{\\bf b_1} + \\dots + x_pA{\\bf b_p}. $$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 19 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "So the vector $A(B{\\bf x})$ is a linear combination of the vectors $A{\\bf b_1}, \\dots, A{\\bf b_p},$ using the entries in ${\\bf x}$ as weights." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 20, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "fragment" } }, "source": [ "A linear combination of vectors is the same as a matrix-vector multiplication. In matrix terms, this linear combination is written:\n", "\n", "$$ A(B{\\bf x}) = [A{\\bf b_1} \\; \\dots \\; A{\\bf b_p}] {\\bf x}.$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "So this matrix $[A{\\bf b_1} \\; \\dots \\; A{\\bf b_p}]$ is what we are looking for!" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 20, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "__Definition.__ If $A$ is an $m \\times n$ matrix and $B$ is $n \\times p$ matrix with columns ${\\bf b_1},\\dots,{\\bf b_p},$ then the product $AB$ is defined as the $m \\times p$ matrix whose columns are $A{\\bf b_1}, \\dots, A{\\bf b_p}.$ That is,\n", "\n", "$$ AB = A[{\\bf b_1} \\; \\dots \\; {\\bf b_p}] = [A{\\bf b_1} \\; \\dots \\; A{\\bf b_p}]. $$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 22 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "This definition means that for any $A$ and $B$ for which $AB$ is defined, then if $C$ = $AB$,\n", "\n", "$$ C{\\bf x} = A(B{\\bf x}). $$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 23 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "That is: _multiplication of matrices_ corresponds to _composition of linear transformations._ " ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 24, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "fragment" } }, "source": [ "Note that when $C = AB$, $C{\\bf x}$ is a vector _in the span of the columns of $A.$_ " ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 24, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "__Example.__ Compute $AB$ where $A = \\left[\\begin{array}{rr}2&3\\\\1&-5\\end{array}\\right]$ and $B = \\left[\\begin{array}{rrr}4&3&6\\\\1&-2&3\\end{array}\\right].$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 26 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "__Solution.__ Write $B = \\left[{\\bf b_1}\\;{\\bf b_2}\\;{\\bf b_3}\\right],$ and compute:\n", "\n", "$$ A{\\bf b_1} = \\left[\\begin{array}{rr}2&3\\\\1&-5\\end{array}\\right]\\left[\\begin{array}{r}4\\\\1\\end{array}\\right],\\;\\;\\;\n", "A{\\bf b_2} = \\left[\\begin{array}{rr}2&3\\\\1&-5\\end{array}\\right]\\left[\\begin{array}{r}3\\\\-2\\end{array}\\right],\\;\\;\\;\n", "A{\\bf b_3} = \\left[\\begin{array}{rr}2&3\\\\1&-5\\end{array}\\right]\\left[\\begin{array}{r}6\\\\3\\end{array}\\right],$$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 27 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "$$ = \\left[\\begin{array}{r}11\\\\-1\\end{array}\\right]\\;\\;\\;\\left[\\begin{array}{r}0\\\\13\\end{array}\\right]\\;\\;\\;\\left[\\begin{array}{r}21\\\\-9\\end{array}\\right].$$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 28, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "fragment" } }, "source": [ "So:\n", "\n", "$$ AB = \\left[A{\\bf b_1}\\;A{\\bf b_2}\\;A{\\bf b_3}\\right] = \\left[\\begin{array}{rrr}11&0&21\\\\-1&13&-9\\end{array}\\right].$$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 28, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "__Example.__ Verify that reflection through the $x_1$ axis followed by reflection through the $x_2$ axis is the same as reflection through the origin." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 30 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "$$\\left[\\begin{array}{rr}-1&0\\\\0&1\\end{array}\\right]\\left[\\begin{array}{rr}1&0\\\\0&-1\\end{array}\\right] = \\left[\\begin{array}{rr}~&~\\\\~&~\\end{array}\\right].$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "$$\\left[\\begin{array}{rr}-1&0\\\\0&1\\end{array}\\right]\\left[\\begin{array}{rr}1&0\\\\0&-1\\end{array}\\right] = \\left[\\begin{array}{rr}-1&0\\\\0&-1\\end{array}\\right].$$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 31, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "fragment" } }, "source": [ "Note that this is a valid proof because every linear transformation of vectors is defined by its standard matrix." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 31, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "__Example.__ If $A$ is a $3 \\times 5$ matrix, and $B$ is a $5 \\times 2$ matrix, what are the sizes of $AB$ and $BA$, if they are defined?" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 33 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "$$\\begin{array}{cccc}A&B&=&AB\\\\\n", "3\\times 5&5 \\times 2&& 3 \\times 2\\\\\n", "\\left[\\begin{array}{rrrrr}*&*&*&*&*\\\\ *&*&*&*&*\\\\ *&*&*&*&*\\end{array}\\right] & \n", "\\left[\\begin{array}{rr}*&*\\\\ *&*\\\\ *&*\\\\ *&*\\\\ *&*\\end{array}\\right] & \n", "= &\n", "\\left[\\begin{array}{rr}*&*\\\\ *&*\\\\ *&*\\end{array}\\right]\n", "\\end{array}$$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 34 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "What about $BA$?" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 35 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "It is not defined, because the number of columns of $B$ does not match the number of rows of $A$." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 36, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "fragment" } }, "source": [ "__Facts.__\n", "\n", "If $A$ is $m\\times n$, and $B$ is $p \\times q$, then $AB$ is defined if and only if $n = p$. If $AB$ is defined, then it is $m \\times q$.\n", "\n", "$$\\begin{array}{cccc}A&B&=&AB\\\\\n", "3\\times \\fbox{5}&\\fbox{5} \\times 2&& 3 \\times 2\\\\\n", "\\end{array}$$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 36, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "## Inner Product View of Matrix Multiplication." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 36 }, "slideshow": { "slide_type": "-" } }, "source": [ "Recall that the inner product of two vectors or sequences ${\\bf u}$ and ${\\bf v}$ is $\\sum_k u_k v_k.$ \n", "\n", "Also recall that one way to define the matrix vector product is $(A{\\bf x})_i =$ inner product of ${\\bf x}$ and row $i$ of $A$." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 39 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "This immediately shows another way to think of matrix multiplication:\n", "\n", "$(AB)_{ij} =$ inner product of row $i$ of $A$ and column $j$ of $B = \\sum_k A_{ik}B_{kj}.$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 40 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "__Example.__ Start with the same matrices as the last example, $A = \\left[\\begin{array}{rr}2&3\\\\1&-5\\end{array}\\right]$ and $B = \\left[\\begin{array}{rrr}4&3&6\\\\1&-2&3\\end{array}\\right].$ Compute the entry in row 1 and column 3 of $C$." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 41, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "fragment" } }, "source": [ "$$AB = \\left[\\begin{array}{rr}\\fbox{2} & \\fbox{3}\\\\1&-5\\end{array}\\right]\\left[\\begin{array}{rrr}4&3&\\fbox{6}\\\\1&-2&\\fbox{3}\\end{array}\\right] = \\left[\\begin{array}{rrc}*&*&2(6)+3(3)\\\\*&*&*\\end{array}\\right] = \\left[\\begin{array}{rrr}*&*&21\\\\*&*&*\\end{array}\\right].$$\n", "\n", "This agrees with the result of the last example, and we could reproduce the whole solution by repeating this for each element of the result matrix." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 41, "slide_helper": "subslide_end", "slide_type": "subslide" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "slide" } }, "source": [ "## Question Time! Q9.1" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 41, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "## Matrix Algebra" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 41 }, "slideshow": { "slide_type": "-" } }, "source": [ "We've defined multiplication of two matrices. What about addition of two matrices?" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 45 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "This is straightfoward: if $A$ and $B$ are the same shape, we get $A + B$ by adding the corresponding elements. (Just like adding vectors.)\n", "\n", "That is, \n", "\n", "$$(A + B)_{ij} = A_{ij} + B_{ij}.$$\n", "\n", "If $A$ and $B$ are not the same shape, $A + B$ is undefined." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 46 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "Furthermore, we define scalar-matrix multiplication just as for vectors:\n", "\n", "$$ (rA)_{ij} = r(A_{ij}).$$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 47 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "So, just as we did for vectors, we can show that the standard properties of addition apply, and that scalar multiplication distributes over addition:\n", "\n", "1. $A + B = B + A$\n", "2. $(A + B) + C = A + (B + C)$\n", "3. $A + 0 = A$\n", "4. $r(A + B) = rA + rB$\n", "5. $(r + s)A = rA + sA$\n", "6. $r(sA) = (rs)A$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 48 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "Furthermore, we find that __some__ (but not all!) of the familiar properties of multiplication apply to matrix multiplication (assume that all sums and products are defined):\n", "\n", "1. $A(BC) = (AB)C$ \n", " * multiplication of matrices is associative\n", "2. $A(B+C) = AB + AC$ \n", " * multiplication on the left distributes over addition\n", "3. $(B+C)A = BA + CA$ \n", " * multiplication on the right distributes over addition\n", "4. $r(AB) = (rA)B = A(rB)$ \n", " * for any scalar $r$\n", "5. $I A = A = AI$ " ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 49, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "fragment" } }, "source": [ "Note that property 1 means that we can write $ABC$ without bothering about parentheses. " ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 49, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "__Now, here is where things get different!__" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 51 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "* In general, $AB$ is __not__ equal to $BA$. Multiplication is __not commutative!__\n", " * Consider $A = \\left[\\begin{array}{rr}1 & 1\\\\1&1\\end{array}\\right]$ and $B = \\left[\\begin{array}{rr}1 & 1\\\\1&2\\end{array}\\right].$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 52 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "* In fact, even if $AB$ is defined, $BA$ may not be defined. \n", " * $AB$ and $BA$ are both defined only if $A$ and $B$ are square." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 53 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "* On the other hand, sometimes $A$ and $B$ __do__ commute.\n", " * Consider $A$ and $B$ as the reflections through the $x_1$ and $x_2$ axis. Then $AB$ and $BA$ both implement reflection through the origin (i.e., the same transformation.) So in this case $AB = BA$." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 54 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "* You cannot, in general, cancel out matrices in a multiplication. That is, if $AC = AB$, it does not follow that $C = B$. \n", " * Consider the case where $A$ is the projection onto one of the axes." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 55 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "* If $AB$ is the zero matrix, you cannot in general conclude that either $A$ or $B$ must be a zero matrix.\n", " * Consider $A = \\left[\\begin{array}{rr}1 & 0\\\\0&0\\end{array}\\right]$ and $B = \\left[\\begin{array}{rr}0 & 0\\\\0&1\\end{array}\\right].$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 55, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "-" } }, "source": [ "__Study and remember these rules. You will use them!__" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 55, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "## Powers of a Matrix" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 55 }, "slideshow": { "slide_type": "-" } }, "source": [ "Equipped now with matrix-matrix multiplication, we can define the powers of a matrix in a straightforward way. For an integer $k > 0$:\n", "\n", "$$ A^k = \\overbrace{A\\cdots A}^k.$$\n", "\n", "Obviously, $A$ must be a square matrix for $A^k$ to be defined." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 59, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "fragment" } }, "source": [ "What should $A^0$ be?\n", "\n", "$A^0{\\bf x}$ should be the result of multiplying ${\\bf x}$ with $A$ zero times. So we define $A^0 = I$." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 59, "slide_helper": "subslide_end", "slide_type": "subslide" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "slide" } }, "source": [ "## Question Time! Q9.2" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 59, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "## The Transpose of a Matrix" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 59 }, "slideshow": { "slide_type": "-" } }, "source": [ "Given an $m \\times n$ matrix $A,$ the _transpose_ of $A$ is the matrix we get by interchanging its rows and columns.\n", "\n", "It is denoted $A^T$. Its shape is $n \\times m$." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 63 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "For example, if:\n", "\n", "$$\n", "\\begin{array}{ccc}\n", "A = \\left[\\begin{array}{rr}a&b\\\\c&d\\end{array}\\right],&\n", "B = \\left[\\begin{array}{rr}-5&2\\\\1&-3\\\\0&4\\end{array}\\right],&\n", "C = \\left[\\begin{array}{rrrr}1&1&1&1\\\\-3&5&-2&7\\end{array}\\right]\n", "\\end{array}\n", "$$\n", "\n", "Then:\n", "\n", "$$\n", "\\begin{array}{ccc}\n", "A^T = \\left[\\begin{array}{rr}a&c\\\\b&d\\end{array}\\right],&\n", "B^T = \\left[\\begin{array}{rrr}-5&1&0\\\\2&-3&4\\end{array}\\right],&\n", "C^T = \\left[\\begin{array}{rr}1&-3\\\\1&5\\\\1&-2\\\\1&7\\end{array}\\right]\n", "\\end{array}\n", "$$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 64 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "The definition can be stated succinctly:\n", "\n", "$$A^T_{ij} = A_{ji}.$$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 65 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "__Rules for Transposes:__\n", "\n", "1. $(A^T)^T = A$\n", "2. $(A + B)^T = A^T + B^T$\n", "3. For any scalar $r$, $(rA)^T = r(A^T)$\n", "4. $(AB)^T = B^TA^T$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 65, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "-" } }, "source": [ "The first three are pretty obvious. \n", "\n", "The last one is a bit different. __Memorize it.__ You will use it: the transpose of a product is the product of the transposes __in reverse order__." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 65, "slide_helper": "subslide_end", "slide_type": "subslide" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "slide" } }, "source": [ "## Question Time! Q9.3" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 65, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "__Question:__ For a vector in ${\\bf x} \\in \\mathbb{R}^n$, what is ${\\bf x}^T$? " ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 69 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "__Answer:__ For the purposes of the definition, we treat ${\\bf x}$ as a $n \\times 1$ matrix. So its transpose is an $1\\times n$ matrix, i.e., a matrix with a single row." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 70 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "__Question:__ For two vectors ${\\bf x}$ and ${\\bf y}$, what is ${\\bf x}^T {\\bf y}$?" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 71, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "fragment" } }, "source": [ "__Answer:__ By the definition of matrix-vector multiplication, ${\\bf x}^T {\\bf y} = \\sum_{i=1}^n x_i y_i.$\n", "\n", "That is, ${\\bf x}^T {\\bf y}$ is the __inner product__ of ${\\bf x}$ and ${\\bf y}$. This simple construction is a very useful one to remember." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 71, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "## The Computational Viewpoint" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 71 }, "slideshow": { "slide_type": "-" } }, "source": [ "You recall in the last lecture I said that in Python/numpy:\n", "\n", " C = A @ B\n", " \n", "was the same as:\n", "\n", " for i in range(k):\n", " C[:,k] = AxIP(A, B[:,k])\n", " \n", "So now you know: `A @ B` is really _matrix multiplication_ of `A` and `B.` :)" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 74, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "fragment" } }, "source": [ "Matrix multiplication is a mainstay of computing. Thousands of applications rely heavily on matrix multiplication. Some examples include\n", "\n", "* Computer graphics and animation\n", "* Google's algorithm for ranking search results\n", "* Modeling mechanical structures such as aircraft and buildings\n", "* Compressing and decompressing audio signals\n", "* Weather modeling and prediction\n", "* Modeling quantum computing\n", "\n", "So minimizing the time required to do matrix multiplication is immensely important." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 74, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "__Complexity.__\n", "\n", "What is the computational complexity of matrix multiplication?" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 76 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "For two $n \\times n$ matrices, consider the definition that uses inner product:\n", "\n", "$$ (AB)_{ij} = \\sum_{k=1}^n A_{ik}B_{kj}.$$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 77 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "So each element of the product $AB$ requires $n$ multiplications and $n$ additions.\n", "\n", "There are $n^2$ elements of $AB$, so the overall computation requires $$2n \\cdot n^2 = 2n^3$$ operations." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 78 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "That's not particularly good news; for two matrices of size 10,000 $\\times$ 10,000 (which is not particularly large in practice), this is 2 trillion operations (2 teraflops)." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 79 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "What is the complexity of matrix-vector multiplication?\n", "\n", "We know that matrix-vector multiplication requires $n$ inner products of size $n$. So, it is $2n^2.$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 80 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "So what is the most efficient way to compute $A^2{\\bf x}$?" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 81, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "fragment" } }, "source": [ "1. First compute $A^2$, then compute $A^2{\\bf x}$: $2n^3 + 2n^2.$\n", "2. First compute $A{\\bf x}$, then compute $A(A{\\bf x}) = 2 \\cdot 2n^2 = 4n^2.$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 81, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "__Parallelization.__\n", "\n", "Although matrix multiplication is computationally demanding, it has a wonderful property: it is _highly parallel_. That is, the computation needed for each element does not require computing the other elements. \n", "\n", "(This is not true, for example, for Gaussian elimination; think about the role of a pivot.)" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 83 }, "slideshow": { "slide_type": "fragment" } }, "source": [ "This means that if we have multiple processors, and each has access to $A$ and $B$, the work can be divided up very cleanly.\n", "\n", "For example, let's say you have $n$ processors. Then each processor can independently compute one column of the result, without needing to know anything about what the other processors are doing. \n", "\n", "Specifically, processor $i$ can compute its column as $A{\\bf b_i}$. \n", "\n", "In that case, since all processors are working in parallel, the elapsed time is reduced to $2n^2.$" ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 84, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "fragment" } }, "source": [ "Even better, say you have $n^2$ processors. Then each processor can compute a single element of the result, \n", "$(AB)_{ij}$ as $\\sum_{k=1}^n A_{ik}B_{kj}$. Then the elapsed time is reduced to $2n$. \n", "\n", "This sort of strategy is used for huge computations like web search and weather modeling." ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 84, "slide_type": "subslide" }, "slideshow": { "slide_type": "slide" } }, "source": [ "__Libraries.__\n", "\n", "The importance of matrix multiplication in practice means that very efficient and carefully constructed libraries have been developed for it.\n", "\n", "An important issue for high performance is how the matrices are actually laid out in memory, and the order in which matrix elements are accessed. \n", "\n", "The premier library is called LAPACK. LAPACK has been developed over the past 40 years and is updated frequently to tune it for new computer hardware. " ] }, { "cell_type": "markdown", "metadata": { "internals": { "frag_helper": "fragment_end", "frag_number": 86, "slide_helper": "subslide_end" }, "slide_helper": "slide_end", "slideshow": { "slide_type": "fragment" } }, "source": [ "Python's \"numpy\" uses LAPACK under the hood for its matrix computations.\n", "\n", "Hence, even though Python is an interpreted language, for doing intensive matrix computations it is very fast, just as fast as compiled code." ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "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.7.7" } }, "nbformat": 4, "nbformat_minor": 1 }