HSG-MCS-HS21_Julia/JuliaTutorial-master/Tutorial_06b_MatrixAlgebra.ipynb

519 lines
12 KiB
Plaintext
Raw Normal View History

2021-11-15 20:14:51 +00:00
{
"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
}