{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Basic Matrix Algebra\n", "\n", "This notebook presents some basic linear algebra in Julia." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "printyellow (generic function with 1 method)" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "using Printf, LinearAlgebra\n", "\n", "include(\"jlFiles/printmat.jl\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Adding and Multiplying: A Matrix and a Scalar" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With a matrix $A$ and a scalar $c$, do\n", "\n", "1. `A*c` (textbook: $Ac$) to multiply each element of $A$ by $c$\n", "\n", "2. `A .+ c` (textbook: $A+cJ$, where $J$ is a matrix of ones) to add $c$ to each element of $A$, and similarly `A .- c` ($A-c$)\n", "\n", "Watch out when the number comes first: `2.+A` is not allowed since it is ambiguous. However, `2.0.+A` and `2 .+ A` both work." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A:\n", " 1 3 \n", " 3 4 \n", "\n", "c:\n", " 10 \n", "\n", "A*c:\n", " 10 30 \n", " 30 40 \n", "\n", "A .+ c:\n", " 11 13 \n", " 13 14 \n", "\n" ] } ], "source": [ "A = [1 3;3 4]\n", "c = 10\n", "\n", "println(\"A:\")\n", "printmat(A)\n", "println(\"c:\")\n", "printmat(c)\n", "\n", "println(\"A*c:\")\n", "printmat(A*c)\n", "\n", "println(\"A .+ c:\")\n", "printmat(A .+ c) #notice the dot in .+" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Adding and Multiplying Two Matrices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With two matrices of the same dimensions ($A$ and $B$), do\n", "\n", "`A+B` (textbook: $A+B$) to add them (element by element), and similarly `A-B` (textbook: $A-B$).\n", "\n", "Multiplying matrices ($A$ and $B$) of conformable dimensions\n", "\n", "`A*B` (textbook: $AB$)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A:\n", " 1 3 \n", " 3 4 \n", "\n", "B:\n", " 1 2 \n", " 3 -2 \n", "\n", "A+B:\n", " 2 5 \n", " 6 2 \n", "\n", "A*B:\n", " 10 -4 \n", " 15 -2 \n", "\n" ] } ], "source": [ "A = [1 3;3 4] #A and B are 2x2 matrices\n", "B = [1 2;3 -2]\n", "println(\"A:\")\n", "printmat(A)\n", "println(\"B:\")\n", "printmat(B)\n", "\n", "println(\"A+B:\")\n", "printmat(A+B)\n", "\n", "println(\"A*B:\")\n", "printmat(A*B)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Transpose\n", "\n", "You can transpose a numerical matrix `A` by `A'`. \n", "\n", "Notice that (in Julia) `A` and `B=A'` share the same elements (changing one changes the other). If you want an independent copy, use `B=copy(A')`.\n", "\n", "For an array of other elements (for instance, strings), use `permutedims(A)` to swap the dimensions." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A: \n", " 1 2 3 \n", " 4 5 6 \n", "\n", "A': \n", " 1 4 \n", " 2 5 \n", " 3 6 \n", "\n" ] } ], "source": [ "A = [1 2 3;4 5 6]\n", "println(\"A: \")\n", "printmat(A)\n", "println(\"A': \")\n", "printmat(A')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Matrix Inverse" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A matrix inverse of an $nxn$ matrix $A$:\n", "\n", "`inv(A)` or `A^(-1)` (textbook: $A^{-1}$)\n", "\n", "The inverse is such that $AA^{-1}=I$ and $A^{-1}A=I$" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A:\n", " 1 3 \n", " 3 4 \n", "\n", "inv(A):\n", " -0.800 0.600\n", " 0.600 -0.200\n", "\n", "inv(A)*A:\n", " 1.000 -0.000\n", " 0.000 1.000\n", "\n" ] } ], "source": [ "A = [1 3;3 4]\n", "println(\"A:\")\n", "printmat(A)\n", "\n", "println(\"inv(A):\")\n", "printmat(inv(A))\n", "\n", "println(\"inv(A)*A:\")\n", "printmat(inv(A)*A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The Identity Matrix\n", "\n", "The identity matrix $I_n$ can often be represented by `I` and then Julia will compare with the surrounding code to create the right dimension. For instance, if `A` is a square matrix, then `I+A` works.\n", "\n", "If you still need to specify the dimension, then `1I(3)` or `Matrix(1I(3))` will create an $I_3$ matrix. (The former is an explicitly diagonal matrix, will the second is a full matrix.) In Julia 1.6 in will be possible to do `1I[1:3,1:3]`." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I + A\n", " 2 3 \n", " 3 5 \n", "\n", "Matrix(1I(3))\n", " 1 0 0 \n", " 0 1 0 \n", " 0 0 1 \n", "\n" ] } ], "source": [ "println(\"I + A\")\n", "printmat(I + A)\n", "\n", "println(\"Matrix(1I(3))\")\n", "printmat(Matrix(1I(3)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vectors: Inner and Outer Products\n", "\n", "There are several different ways to think about a vector in mathematics: as a $K \\times 1$ matrix (a column vector), a $1 \\times K$ matrix (a row vector) or just a flat $K-$vector. Julia uses flat vectors but they are mostly interchangable with column vectors. \n", "\n", "The inner product of two (column) vectors with $k$ elements is calculated as `x'z` or `dot(x,y)` (textbook: $x'z$ or $x \\cdot z$) to get a scalar. (You can also use or `x⋅y` where the dot is obtained by `\\cdot + TAB`, but that is sometimes hard to distinguish from or `x.y`) \n", "\n", "In contrast, the outer of two (column) vectors with $k$ elements is calculated\n", "(textbook: $xz'$) to get a $k\\times k$ matrix." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x and z\n", " 10 2 \n", " 11 5 \n", "\n", "x'z: \n", " 75 \n", "x*z':\n", " 20 50 \n", " 22 55 \n", "\n" ] } ], "source": [ "x = [10,11] #[10;11] gives the same\n", "z = [2,5]\n", "println(\"x and z\")\n", "printmat([x z])\n", "\n", "println(\"x'z: \")\n", "printlnPs(x'z) #dot(x,z) gives the same\n", "\n", "println(\"x*z':\")\n", "printmat(x*z')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vectors: Quadratic Forms\n", "\n", "A quadratic form ($A$ is an $n \\times n$ matrix and x is an $n$ vector): `x'A*x` (textbook: $x'Ax$) to get a scalar. \n", "\n", "(In Julia 1.5+ there is also the form `dot(x,A,x)`)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x:\n", " 10 \n", " 11 \n", "\n", "A:\n", " 1 3 \n", " 3 4 \n", "\n", "x'A*x: \n", " 1244 \n" ] } ], "source": [ "A = [1 3;3 4]\n", "x = [10,11]\n", "\n", "println(\"x:\")\n", "printmat(x)\n", "println(\"A:\")\n", "printmat(A)\n", "\n", "println(\"x'A*x: \")\n", "printlnPs(x'A*x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vectors: Extracting Vectors from Matrices\n", "\n", "Notice that `A[1,:]` and `A[:,1]` both give flat vectors. In case you want a row vector use `A[1:1,:]`." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2-element Vector{Int64}:\n", " 1\n", " 3" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[1,:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## OLS Notation\n", "\n", "$X'X$ or $\\sum\\nolimits_{t=1}^{T}x_{t}x_{t}^{\\prime}$?\n", "\n", "Let $x_t$ be a (column) vector with values of $K$ regressors for observation $t$. Then $x_{t}x_{t}^{\\prime}$ is the outer product (a $K\\times K$ matrix) and $\\sum\\nolimits_{t=1}^{T}x_{t}x_{t}^{\\prime}$ is just the sum (of each element) across the $T$ observations.\n", "\n", "We can calculate the same thing by (a) letting $X$ be a $T\\times K$ matrix with $x_{t}^{\\prime}$ in row $t$ and (b) then do $X'X$." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "X\n", " 1.000 -1.000\n", " 1.000 0.000\n", " 1.000 1.000\n", "\n", "sum of outer products, three versions\n", " 3.000 0.000\n", " 0.000 2.000\n", "\n", " 3.000 0.000\n", " 0.000 2.000\n", "\n", " 3.000 0.000\n", " 0.000 2.000\n", "\n" ] } ], "source": [ "x₁ = [1,-1] #a (column) vector\n", "x₂ = [1,0]\n", "x₃ = [1,1.0]\n", "\n", "X = [x₁';x₂';x₃']\n", "\n", "println(\"X\")\n", "printmat(X)\n", "\n", "(T,K) = (size(X,1),size(X,2))\n", "\n", "Sxx1 = x₁*x₁' + x₂*x₂' + x₃*x₃' #just to illustrate\n", "\n", "Sxx2 = zeros(K,K)\n", "for t = 1:T\n", " #global Sxx2 #only needed in script\n", " Sxx2 = Sxx2 + X[t,:]*X[t,:]' #X[t,:] becomes a flat vector\n", "end\n", "\n", "Sxx3 = X'X\n", "\n", "println(\"sum of outer products, three versions\")\n", "printmat(Sxx1)\n", "printmat(Sxx2)\n", "printmat(Sxx3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "@webio": { "lastCommId": null, "lastKernelId": null }, "anaconda-cloud": {}, "kernelspec": { "display_name": "Julia 1.6.0", "language": "julia", "name": "julia-1.6" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "1.6.0" } }, "nbformat": 4, "nbformat_minor": 1 }