├── .gitignore ├── Manifest.toml ├── Project.toml ├── README.md ├── _research └── wip │ ├── approximation │ ├── global │ │ └── interpolation.md │ └── local │ │ ├── conditioning-poly.jl │ │ └── piecewise-poly.jl │ ├── discrete-dp │ └── value-function-iteration │ │ ├── caraiani-vfi.jl │ │ ├── edmond-vfi.jl │ │ ├── edmond_vfi_collocation.jl │ │ ├── fedor-vfi.jl │ │ ├── florian-vfi.jl │ │ ├── mccandless-vfi.jl │ │ └── rudik-vfi.jl │ ├── optimisation │ ├── bracketing │ │ ├── bracket_min.jl │ │ └── fibonacci_search.jl │ ├── derivatives │ │ └── symbolic_diff.jl │ ├── direct │ │ └── nelder-mead.jl │ ├── gradient │ │ └── gradient-descent.jl │ └── local-descent │ │ └── line-search.jl │ ├── quadrature │ ├── basics.jl │ └── trapezoid.jl │ └── root-finding │ ├── multivariate │ ├── broyden.jl │ ├── levenberg.jl │ ├── newton_mv.jl │ └── nl_least_squares.jl │ └── univariate │ ├── bisection.jl │ ├── fp_iteration.jl │ ├── newton.jl │ └── secant.jl ├── backups └── topic-5 backup 1.jl ├── notebooks ├── aiyagari_example.ipynb ├── topic-1.jl ├── topic-10.jl ├── topic-2.jl ├── topic-3.jl ├── topic-4.jl ├── topic-5.jl ├── topic-6.jl ├── topic-7.jl ├── topic-8.jl └── topic-9.jl ├── package-lock.json ├── papers ├── aruoba-fernandez.pdf └── coleman-lyon-maliar.pdf └── scripts ├── hd_dpp.jl ├── intro.jl ├── iterative.jl ├── jump-example.jl ├── jump-rosenbrock.jl └── rjulia.jl /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # DrWatson Project Structure # 3 | ################################################################################ 4 | 5 | # Folders to ignore - files may be too large, too many, etc. NOTE: EDIT IF NEEDED. 6 | data 7 | videos 8 | plots 9 | #notebooks 10 | #_research 11 | 12 | ################################################################################ 13 | # Julia # 14 | ################################################################################ 15 | 16 | # Files generated by invoking Julia with --code-coverage 17 | *.jl.cov 18 | *.jl.*.cov 19 | 20 | # Files generated by invoking Julia with --track-allocation 21 | *.jl.mem 22 | 23 | # System-specific files and directories generated by the BinaryProvider and 24 | # BinDeps packages. 25 | # They contain absolute paths, and so should not be committed 26 | deps/deps.jl 27 | deps/build.log 28 | deps/downloads/ 29 | deps/usr/ 30 | deps/src/ 31 | 32 | # Build artifacts for creating documentation generated by the Documenter package 33 | docs/build/ 34 | docs/site/ 35 | 36 | ################################################################################ 37 | # Jupyter Notebook # 38 | ################################################################################ 39 | 40 | .ipynb_checkpoints 41 | */.ipynb_checkpoints/* 42 | 43 | ################################################################################ 44 | # Microsoft Office # 45 | ################################################################################ 46 | 47 | *.tmp 48 | 49 | # Word temporary 50 | ~$*.doc* 51 | 52 | # Word Auto Backup File 53 | Backup of *.doc* 54 | 55 | # Excel temporary 56 | ~$*.xls* 57 | 58 | # Excel Backup File 59 | *.xlk 60 | 61 | # PowerPoint temporary 62 | ~$*.ppt* 63 | 64 | ################################################################################ 65 | # LaTeX # 66 | ################################################################################ 67 | 68 | ## Core latex/pdflatex auxiliary files: 69 | *.aux 70 | *.lof 71 | *.log 72 | *.lot 73 | *.fls 74 | *.out 75 | *.toc 76 | *.fmt 77 | *.fot 78 | *.cb 79 | *.cb2 80 | .*.lb 81 | 82 | ## Intermediate documents: 83 | *.dvi 84 | *.xdv 85 | *-converted-to.* 86 | # these rules will exclude image files for figures, et cetera... 87 | # *.ps 88 | # *.eps 89 | # *.pdf 90 | 91 | ## Generated if empty string given at "Please type another file name for output:" 92 | .pdf 93 | 94 | ## Bibliography auxiliary files (bibtex/biblatex/biber): 95 | *.bbl 96 | *.bcf 97 | *.blg 98 | *-blx.aux 99 | *-blx.bib 100 | *.run.xml 101 | 102 | ## Build tool auxiliary files: 103 | *.fdb_latexmk 104 | *.synctex 105 | *.synctex(busy) 106 | *.synctex.gz 107 | *.synctex.gz(busy) 108 | *.pdfsync 109 | 110 | ## Build tool directories for auxiliary files 111 | # latexrun 112 | latex.out/ 113 | 114 | ## Auxiliary and intermediate files from other packages: 115 | # algorithms 116 | *.alg 117 | *.loa 118 | 119 | # achemso 120 | acs-*.bib 121 | 122 | # amsthm 123 | *.thm 124 | 125 | # beamer 126 | *.nav 127 | *.pre 128 | *.snm 129 | *.vrb 130 | 131 | # changes 132 | *.soc 133 | 134 | # comment 135 | *.cut 136 | 137 | # cprotect 138 | *.cpt 139 | 140 | # elsarticle (documentclass of Elsevier journals) 141 | *.spl 142 | 143 | # endnotes 144 | *.ent 145 | 146 | # fixme 147 | *.lox 148 | 149 | # feynmf/feynmp 150 | *.mf 151 | *.mp 152 | *.t[1-9] 153 | *.t[1-9][0-9] 154 | *.tfm 155 | 156 | #(r)(e)ledmac/(r)(e)ledpar 157 | *.end 158 | *.?end 159 | *.[1-9] 160 | *.[1-9][0-9] 161 | *.[1-9][0-9][0-9] 162 | *.[1-9]R 163 | *.[1-9][0-9]R 164 | *.[1-9][0-9][0-9]R 165 | *.eledsec[1-9] 166 | *.eledsec[1-9]R 167 | *.eledsec[1-9][0-9] 168 | *.eledsec[1-9][0-9]R 169 | *.eledsec[1-9][0-9][0-9] 170 | *.eledsec[1-9][0-9][0-9]R 171 | 172 | # glossaries 173 | *.acn 174 | *.acr 175 | *.glg 176 | *.glo 177 | *.gls 178 | *.glsdefs 179 | 180 | # gnuplottex 181 | *-gnuplottex-* 182 | 183 | # gregoriotex 184 | *.gaux 185 | *.gtex 186 | 187 | # htlatex 188 | *.4ct 189 | *.4tc 190 | *.idv 191 | *.lg 192 | *.trc 193 | *.xref 194 | 195 | # hyperref 196 | *.brf 197 | 198 | # knitr 199 | *-concordance.tex 200 | 201 | # listings 202 | *.lol 203 | 204 | # luatexja-ruby 205 | *.ltjruby 206 | 207 | # makeidx 208 | *.idx 209 | *.ilg 210 | *.ind 211 | *.ist 212 | 213 | # minitoc 214 | *.maf 215 | *.mlf 216 | *.mlt 217 | *.mtc[0-9]* 218 | *.slf[0-9]* 219 | *.slt[0-9]* 220 | *.stc[0-9]* 221 | 222 | # minted 223 | _minted* 224 | *.pyg 225 | 226 | # morewrites 227 | *.mw 228 | 229 | # nomencl 230 | *.nlg 231 | *.nlo 232 | *.nls 233 | 234 | # pax 235 | *.pax 236 | 237 | # pdfpcnotes 238 | *.pdfpc 239 | 240 | # sagetex 241 | *.sagetex.sage 242 | *.sagetex.py 243 | *.sagetex.scmd 244 | 245 | # scrwfile 246 | *.wrt 247 | 248 | # sympy 249 | *.sout 250 | *.sympy 251 | sympy-plots-for-*.tex/ 252 | 253 | # pdfcomment 254 | *.upa 255 | *.upb 256 | 257 | # pythontex 258 | *.pytxcode 259 | pythontex-files-*/ 260 | 261 | # tcolorbox 262 | *.listing 263 | 264 | # thmtools 265 | *.loe 266 | 267 | # TikZ & PGF 268 | *.dpth 269 | *.md5 270 | *.auxlock 271 | 272 | # todonotes 273 | *.tdo 274 | 275 | # vhistory 276 | *.hst 277 | *.ver 278 | 279 | # easy-todo 280 | *.lod 281 | 282 | # xcolor 283 | *.xcp 284 | 285 | # xmpincl 286 | *.xmpi 287 | 288 | # xindy 289 | *.xdy 290 | 291 | # xypic precompiled matrices 292 | *.xyc 293 | 294 | # endfloat 295 | *.ttt 296 | *.fff 297 | 298 | # Latexian 299 | TSWLatexianTemp* 300 | 301 | ## Editors: 302 | # WinEdt 303 | *.bak 304 | *.sav 305 | 306 | # Texpad 307 | .texpadtmp 308 | 309 | # LyX 310 | *.lyx~ 311 | 312 | # Kile 313 | *.backup 314 | 315 | # KBibTeX 316 | *~[0-9]* 317 | 318 | # auto folder when using emacs and auctex 319 | ./auto/* 320 | *.el 321 | 322 | # expex forward references with \gathertags 323 | *-tags.tex 324 | 325 | # standalone packages 326 | *.sta 327 | 328 | ### LaTeX Patch ### 329 | # glossaries 330 | *.glstex 331 | 332 | ################################################################################ 333 | # Operating systems # 334 | ################################################################################ 335 | 336 | ######################################## 337 | # Linux # 338 | ######################################## 339 | 340 | *~ 341 | 342 | # temporary files which can be created if a process still has a handle open of 343 | # a deleted file 344 | .fuse_hidden* 345 | 346 | # KDE directory preferences 347 | .directory 348 | 349 | # Linux trash folder which might appear on any partition or disk 350 | .Trash-* 351 | 352 | # .nfs files are created when an open file is removed but is still being accessed 353 | .nfs* 354 | 355 | ######################################## 356 | # macOS # 357 | ######################################## 358 | 359 | # General 360 | .DS_Store 361 | .AppleDouble 362 | .LSOverride 363 | 364 | # Icon must end with two \r 365 | Icon 366 | 367 | # Thumbnails 368 | ._* 369 | 370 | # Files that might appear in the root of a volume 371 | .DocumentRevisions-V100 372 | .fseventsd 373 | .Spotlight-V100 374 | .TemporaryItems 375 | .Trashes 376 | .VolumeIcon.icns 377 | .com.apple.timemachine.donotpresent 378 | 379 | # Directories potentially created on remote AFP share 380 | .AppleDB 381 | .AppleDesktop 382 | Network Trash Folder 383 | Temporary Items 384 | .apdisk 385 | 386 | ######################################## 387 | # Windows # 388 | ######################################## 389 | 390 | # Windows thumbnail cache files 391 | Thumbs.db 392 | ehthumbs.db 393 | ehthumbs_vista.db 394 | 395 | # Dump file 396 | *.stackdump 397 | 398 | # Folder config file 399 | [Dd]esktop.ini 400 | 401 | # Recycle Bin used on file shares 402 | $RECYCLE.BIN/ 403 | 404 | # Windows Installer files 405 | *.cab 406 | *.msi 407 | *.msix 408 | *.msm 409 | *.msp 410 | 411 | # Windows shortcuts 412 | *.lnk 413 | 414 | # Workspace files are user-specific 415 | CompEcon.code-workspace 416 | 417 | ## Acknowledgements 418 | # Many thanks to `https://gitignore.io/`, written and maintained by Joe Blau, which contributed much material to this gitignore file. 419 | -------------------------------------------------------------------------------- /Manifest.toml: -------------------------------------------------------------------------------- 1 | # This file is machine-generated - editing it directly is not advised 2 | 3 | julia_version = "1.9.0" 4 | manifest_format = "2.0" 5 | project_hash = "39d0d5866236472d6bc1a58c4e663ea8a2a2e057" 6 | 7 | [[deps.ArgTools]] 8 | uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" 9 | version = "1.1.1" 10 | 11 | [[deps.Artifacts]] 12 | uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" 13 | 14 | [[deps.Base64]] 15 | uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" 16 | 17 | [[deps.BitFlags]] 18 | git-tree-sha1 = "43b1a4a8f797c1cddadf60499a8a077d4af2cd2d" 19 | uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35" 20 | version = "0.1.7" 21 | 22 | [[deps.Bzip2_jll]] 23 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 24 | git-tree-sha1 = "19a35467a82e236ff51bc17a3a44b69ef35185a2" 25 | uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0" 26 | version = "1.0.8+0" 27 | 28 | [[deps.Cairo_jll]] 29 | deps = ["Artifacts", "Bzip2_jll", "CompilerSupportLibraries_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"] 30 | git-tree-sha1 = "4b859a208b2397a7a623a03449e4636bdb17bcf2" 31 | uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a" 32 | version = "1.16.1+1" 33 | 34 | [[deps.CodecZlib]] 35 | deps = ["TranscodingStreams", "Zlib_jll"] 36 | git-tree-sha1 = "9c209fb7536406834aa938fb149964b985de6c83" 37 | uuid = "944b1d66-785c-5afd-91f1-9de20f533193" 38 | version = "0.7.1" 39 | 40 | [[deps.ColorSchemes]] 41 | deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "PrecompileTools", "Random"] 42 | git-tree-sha1 = "be6ab11021cd29f0344d5c4357b163af05a48cba" 43 | uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4" 44 | version = "3.21.0" 45 | 46 | [[deps.ColorTypes]] 47 | deps = ["FixedPointNumbers", "Random"] 48 | git-tree-sha1 = "eb7f0f8307f71fac7c606984ea5fb2817275d6e4" 49 | uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" 50 | version = "0.11.4" 51 | 52 | [[deps.ColorVectorSpace]] 53 | deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "SpecialFunctions", "Statistics", "TensorCore"] 54 | git-tree-sha1 = "600cc5508d66b78aae350f7accdb58763ac18589" 55 | uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4" 56 | version = "0.9.10" 57 | 58 | [[deps.Colors]] 59 | deps = ["ColorTypes", "FixedPointNumbers", "Reexport"] 60 | git-tree-sha1 = "fc08e5930ee9a4e03f84bfb5211cb54e7769758a" 61 | uuid = "5ae59095-9a9b-59fe-a467-6f913c188581" 62 | version = "0.12.10" 63 | 64 | [[deps.Compat]] 65 | deps = ["UUIDs"] 66 | git-tree-sha1 = "7a60c856b9fa189eb34f5f8a6f6b5529b7942957" 67 | uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" 68 | version = "4.6.1" 69 | weakdeps = ["Dates", "LinearAlgebra"] 70 | 71 | [deps.Compat.extensions] 72 | CompatLinearAlgebraExt = "LinearAlgebra" 73 | 74 | [[deps.CompilerSupportLibraries_jll]] 75 | deps = ["Artifacts", "Libdl"] 76 | uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" 77 | version = "1.0.2+0" 78 | 79 | [[deps.ConcurrentUtilities]] 80 | deps = ["Serialization", "Sockets"] 81 | git-tree-sha1 = "96d823b94ba8d187a6d8f0826e731195a74b90e9" 82 | uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb" 83 | version = "2.2.0" 84 | 85 | [[deps.ConstructionBase]] 86 | deps = ["LinearAlgebra"] 87 | git-tree-sha1 = "738fec4d684a9a6ee9598a8bfee305b26831f28c" 88 | uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" 89 | version = "1.5.2" 90 | 91 | [deps.ConstructionBase.extensions] 92 | ConstructionBaseIntervalSetsExt = "IntervalSets" 93 | ConstructionBaseStaticArraysExt = "StaticArrays" 94 | 95 | [deps.ConstructionBase.weakdeps] 96 | IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" 97 | StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" 98 | 99 | [[deps.Contour]] 100 | git-tree-sha1 = "d05d9e7b7aedff4e5b51a029dced05cfb6125781" 101 | uuid = "d38c429a-6771-53c6-b99e-75d170b6e991" 102 | version = "0.6.2" 103 | 104 | [[deps.DataAPI]] 105 | git-tree-sha1 = "8da84edb865b0b5b0100c0666a9bc9a0b71c553c" 106 | uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" 107 | version = "1.15.0" 108 | 109 | [[deps.DataStructures]] 110 | deps = ["Compat", "InteractiveUtils", "OrderedCollections"] 111 | git-tree-sha1 = "d1fff3a548102f48987a52a2e0d114fa97d730f0" 112 | uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" 113 | version = "0.18.13" 114 | 115 | [[deps.Dates]] 116 | deps = ["Printf"] 117 | uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" 118 | 119 | [[deps.DelimitedFiles]] 120 | deps = ["Mmap"] 121 | git-tree-sha1 = "9e2f36d3c96a820c678f2f1f1782582fcf685bae" 122 | uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab" 123 | version = "1.9.1" 124 | 125 | [[deps.DocStringExtensions]] 126 | deps = ["LibGit2"] 127 | git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d" 128 | uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" 129 | version = "0.9.3" 130 | 131 | [[deps.Downloads]] 132 | deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] 133 | uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" 134 | version = "1.6.0" 135 | 136 | [[deps.Expat_jll]] 137 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 138 | git-tree-sha1 = "bad72f730e9e91c08d9427d5e8db95478a3c323d" 139 | uuid = "2e619515-83b5-522b-bb60-26c02a35a201" 140 | version = "2.4.8+0" 141 | 142 | [[deps.FFMPEG]] 143 | deps = ["FFMPEG_jll"] 144 | git-tree-sha1 = "b57e3acbe22f8484b4b5ff66a7499717fe1a9cc8" 145 | uuid = "c87230d0-a227-11e9-1b43-d7ebe4e7570a" 146 | version = "0.4.1" 147 | 148 | [[deps.FFMPEG_jll]] 149 | deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "PCRE2_jll", "Pkg", "Zlib_jll", "libaom_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"] 150 | git-tree-sha1 = "74faea50c1d007c85837327f6775bea60b5492dd" 151 | uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5" 152 | version = "4.4.2+2" 153 | 154 | [[deps.FileWatching]] 155 | uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" 156 | 157 | [[deps.FixedPointNumbers]] 158 | deps = ["Statistics"] 159 | git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc" 160 | uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" 161 | version = "0.8.4" 162 | 163 | [[deps.Fontconfig_jll]] 164 | deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Pkg", "Zlib_jll"] 165 | git-tree-sha1 = "21efd19106a55620a188615da6d3d06cd7f6ee03" 166 | uuid = "a3f928ae-7b40-5064-980b-68af3947d34b" 167 | version = "2.13.93+0" 168 | 169 | [[deps.Formatting]] 170 | deps = ["Printf"] 171 | git-tree-sha1 = "8339d61043228fdd3eb658d86c926cb282ae72a8" 172 | uuid = "59287772-0a20-5a39-b81b-1366585eb4c0" 173 | version = "0.4.2" 174 | 175 | [[deps.FreeType2_jll]] 176 | deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] 177 | git-tree-sha1 = "87eb71354d8ec1a96d4a7636bd57a7347dde3ef9" 178 | uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7" 179 | version = "2.10.4+0" 180 | 181 | [[deps.FriBidi_jll]] 182 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 183 | git-tree-sha1 = "aa31987c2ba8704e23c6c8ba8a4f769d5d7e4f91" 184 | uuid = "559328eb-81f9-559d-9380-de523a88c83c" 185 | version = "1.0.10+0" 186 | 187 | [[deps.GLFW_jll]] 188 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pkg", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"] 189 | git-tree-sha1 = "d972031d28c8c8d9d7b41a536ad7bb0c2579caca" 190 | uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89" 191 | version = "3.3.8+0" 192 | 193 | [[deps.GR]] 194 | deps = ["Artifacts", "Base64", "DelimitedFiles", "Downloads", "GR_jll", "HTTP", "JSON", "Libdl", "LinearAlgebra", "Pkg", "Preferences", "Printf", "Random", "Serialization", "Sockets", "TOML", "Tar", "Test", "UUIDs", "p7zip_jll"] 195 | git-tree-sha1 = "8b8a2fd4536ece6e554168c21860b6820a8a83db" 196 | uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71" 197 | version = "0.72.7" 198 | 199 | [[deps.GR_jll]] 200 | deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Qt5Base_jll", "Zlib_jll", "libpng_jll"] 201 | git-tree-sha1 = "19fad9cd9ae44847fe842558a744748084a722d1" 202 | uuid = "d2c73de3-f751-5644-a686-071e5b155ba9" 203 | version = "0.72.7+0" 204 | 205 | [[deps.Gettext_jll]] 206 | deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "XML2_jll"] 207 | git-tree-sha1 = "9b02998aba7bf074d14de89f9d37ca24a1a0b046" 208 | uuid = "78b55507-aeef-58d4-861c-77aaff3498b1" 209 | version = "0.21.0+0" 210 | 211 | [[deps.Glib_jll]] 212 | deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE2_jll", "Pkg", "Zlib_jll"] 213 | git-tree-sha1 = "d3b3624125c1474292d0d8ed0f65554ac37ddb23" 214 | uuid = "7746bdde-850d-59dc-9ae8-88ece973131d" 215 | version = "2.74.0+2" 216 | 217 | [[deps.Graphite2_jll]] 218 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 219 | git-tree-sha1 = "344bf40dcab1073aca04aa0df4fb092f920e4011" 220 | uuid = "3b182d85-2403-5c21-9c21-1e1f0cc25472" 221 | version = "1.3.14+0" 222 | 223 | [[deps.Grisu]] 224 | git-tree-sha1 = "53bb909d1151e57e2484c3d1b53e19552b887fb2" 225 | uuid = "42e2da0e-8278-4e71-bc24-59509adca0fe" 226 | version = "1.0.2" 227 | 228 | [[deps.HTTP]] 229 | deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"] 230 | git-tree-sha1 = "5e77dbf117412d4f164a464d610ee6050cc75272" 231 | uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" 232 | version = "1.9.6" 233 | 234 | [[deps.HarfBuzz_jll]] 235 | deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "Graphite2_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg"] 236 | git-tree-sha1 = "129acf094d168394e80ee1dc4bc06ec835e510a3" 237 | uuid = "2e76f6c2-a576-52d4-95c1-20adfe4de566" 238 | version = "2.8.1+1" 239 | 240 | [[deps.InteractiveUtils]] 241 | deps = ["Markdown"] 242 | uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" 243 | 244 | [[deps.IrrationalConstants]] 245 | git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2" 246 | uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" 247 | version = "0.2.2" 248 | 249 | [[deps.JLFzf]] 250 | deps = ["Pipe", "REPL", "Random", "fzf_jll"] 251 | git-tree-sha1 = "f377670cda23b6b7c1c0b3893e37451c5c1a2185" 252 | uuid = "1019f520-868f-41f5-a6de-eb00f4b6a39c" 253 | version = "0.1.5" 254 | 255 | [[deps.JLLWrappers]] 256 | deps = ["Preferences"] 257 | git-tree-sha1 = "abc9885a7ca2052a736a600f7fa66209f96506e1" 258 | uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" 259 | version = "1.4.1" 260 | 261 | [[deps.JSON]] 262 | deps = ["Dates", "Mmap", "Parsers", "Unicode"] 263 | git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" 264 | uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" 265 | version = "0.21.4" 266 | 267 | [[deps.JpegTurbo_jll]] 268 | deps = ["Artifacts", "JLLWrappers", "Libdl"] 269 | git-tree-sha1 = "6f2675ef130a300a112286de91973805fcc5ffbc" 270 | uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8" 271 | version = "2.1.91+0" 272 | 273 | [[deps.LAME_jll]] 274 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 275 | git-tree-sha1 = "f6250b16881adf048549549fba48b1161acdac8c" 276 | uuid = "c1c5ebd0-6772-5130-a774-d5fcae4a789d" 277 | version = "3.100.1+0" 278 | 279 | [[deps.LERC_jll]] 280 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 281 | git-tree-sha1 = "bf36f528eec6634efc60d7ec062008f171071434" 282 | uuid = "88015f11-f218-50d7-93a8-a6af411a945d" 283 | version = "3.0.0+1" 284 | 285 | [[deps.LZO_jll]] 286 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 287 | git-tree-sha1 = "e5b909bcf985c5e2605737d2ce278ed791b89be6" 288 | uuid = "dd4b983a-f0e5-5f8d-a1b7-129d4a5fb1ac" 289 | version = "2.10.1+0" 290 | 291 | [[deps.LaTeXStrings]] 292 | git-tree-sha1 = "f2355693d6778a178ade15952b7ac47a4ff97996" 293 | uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" 294 | version = "1.3.0" 295 | 296 | [[deps.Latexify]] 297 | deps = ["Formatting", "InteractiveUtils", "LaTeXStrings", "MacroTools", "Markdown", "OrderedCollections", "Printf", "Requires"] 298 | git-tree-sha1 = "099e356f267354f46ba65087981a77da23a279b7" 299 | uuid = "23fbe1c1-3f47-55db-b15f-69d7ec21a316" 300 | version = "0.16.0" 301 | 302 | [deps.Latexify.extensions] 303 | DataFramesExt = "DataFrames" 304 | SymEngineExt = "SymEngine" 305 | 306 | [deps.Latexify.weakdeps] 307 | DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" 308 | SymEngine = "123dc426-2d89-5057-bbad-38513e3affd8" 309 | 310 | [[deps.LibCURL]] 311 | deps = ["LibCURL_jll", "MozillaCACerts_jll"] 312 | uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" 313 | version = "0.6.3" 314 | 315 | [[deps.LibCURL_jll]] 316 | deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] 317 | uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" 318 | version = "7.84.0+0" 319 | 320 | [[deps.LibGit2]] 321 | deps = ["Base64", "NetworkOptions", "Printf", "SHA"] 322 | uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" 323 | 324 | [[deps.LibSSH2_jll]] 325 | deps = ["Artifacts", "Libdl", "MbedTLS_jll"] 326 | uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" 327 | version = "1.10.2+0" 328 | 329 | [[deps.Libdl]] 330 | uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" 331 | 332 | [[deps.Libffi_jll]] 333 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 334 | git-tree-sha1 = "0b4a5d71f3e5200a7dff793393e09dfc2d874290" 335 | uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490" 336 | version = "3.2.2+1" 337 | 338 | [[deps.Libgcrypt_jll]] 339 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgpg_error_jll", "Pkg"] 340 | git-tree-sha1 = "64613c82a59c120435c067c2b809fc61cf5166ae" 341 | uuid = "d4300ac3-e22c-5743-9152-c294e39db1e4" 342 | version = "1.8.7+0" 343 | 344 | [[deps.Libglvnd_jll]] 345 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll", "Xorg_libXext_jll"] 346 | git-tree-sha1 = "6f73d1dd803986947b2c750138528a999a6c7733" 347 | uuid = "7e76a0d4-f3c7-5321-8279-8d96eeed0f29" 348 | version = "1.6.0+0" 349 | 350 | [[deps.Libgpg_error_jll]] 351 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 352 | git-tree-sha1 = "c333716e46366857753e273ce6a69ee0945a6db9" 353 | uuid = "7add5ba3-2f88-524e-9cd5-f83b8a55f7b8" 354 | version = "1.42.0+0" 355 | 356 | [[deps.Libiconv_jll]] 357 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 358 | git-tree-sha1 = "c7cb1f5d892775ba13767a87c7ada0b980ea0a71" 359 | uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" 360 | version = "1.16.1+2" 361 | 362 | [[deps.Libmount_jll]] 363 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 364 | git-tree-sha1 = "9c30530bf0effd46e15e0fdcf2b8636e78cbbd73" 365 | uuid = "4b2f31a3-9ecc-558c-b454-b3730dcb73e9" 366 | version = "2.35.0+0" 367 | 368 | [[deps.Libtiff_jll]] 369 | deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "LERC_jll", "Libdl", "Pkg", "Zlib_jll", "Zstd_jll"] 370 | git-tree-sha1 = "3eb79b0ca5764d4799c06699573fd8f533259713" 371 | uuid = "89763e89-9b03-5906-acba-b20f662cd828" 372 | version = "4.4.0+0" 373 | 374 | [[deps.Libuuid_jll]] 375 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 376 | git-tree-sha1 = "7f3efec06033682db852f8b3bc3c1d2b0a0ab066" 377 | uuid = "38a345b3-de98-5d2b-a5d3-14cd9215e700" 378 | version = "2.36.0+0" 379 | 380 | [[deps.LinearAlgebra]] 381 | deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] 382 | uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 383 | 384 | [[deps.LogExpFunctions]] 385 | deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] 386 | git-tree-sha1 = "0a1b7c2863e44523180fdb3146534e265a91870b" 387 | uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" 388 | version = "0.3.23" 389 | 390 | [deps.LogExpFunctions.extensions] 391 | LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" 392 | LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables" 393 | LogExpFunctionsInverseFunctionsExt = "InverseFunctions" 394 | 395 | [deps.LogExpFunctions.weakdeps] 396 | ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" 397 | ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0" 398 | InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" 399 | 400 | [[deps.Logging]] 401 | uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" 402 | 403 | [[deps.LoggingExtras]] 404 | deps = ["Dates", "Logging"] 405 | git-tree-sha1 = "cedb76b37bc5a6c702ade66be44f831fa23c681e" 406 | uuid = "e6f89c97-d47a-5376-807f-9c37f3926c36" 407 | version = "1.0.0" 408 | 409 | [[deps.MacroTools]] 410 | deps = ["Markdown", "Random"] 411 | git-tree-sha1 = "42324d08725e200c23d4dfb549e0d5d89dede2d2" 412 | uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" 413 | version = "0.5.10" 414 | 415 | [[deps.Markdown]] 416 | deps = ["Base64"] 417 | uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" 418 | 419 | [[deps.MbedTLS]] 420 | deps = ["Dates", "MbedTLS_jll", "MozillaCACerts_jll", "Random", "Sockets"] 421 | git-tree-sha1 = "03a9b9718f5682ecb107ac9f7308991db4ce395b" 422 | uuid = "739be429-bea8-5141-9913-cc70e7f3736d" 423 | version = "1.1.7" 424 | 425 | [[deps.MbedTLS_jll]] 426 | deps = ["Artifacts", "Libdl"] 427 | uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" 428 | version = "2.28.2+0" 429 | 430 | [[deps.Measures]] 431 | git-tree-sha1 = "c13304c81eec1ed3af7fc20e75fb6b26092a1102" 432 | uuid = "442fdcdd-2543-5da2-b0f3-8c86c306513e" 433 | version = "0.3.2" 434 | 435 | [[deps.Missings]] 436 | deps = ["DataAPI"] 437 | git-tree-sha1 = "f66bdc5de519e8f8ae43bdc598782d35a25b1272" 438 | uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28" 439 | version = "1.1.0" 440 | 441 | [[deps.Mmap]] 442 | uuid = "a63ad114-7e13-5084-954f-fe012c677804" 443 | 444 | [[deps.MozillaCACerts_jll]] 445 | uuid = "14a3606d-f60d-562e-9121-12d972cd8159" 446 | version = "2022.10.11" 447 | 448 | [[deps.NaNMath]] 449 | deps = ["OpenLibm_jll"] 450 | git-tree-sha1 = "0877504529a3e5c3343c6f8b4c0381e57e4387e4" 451 | uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" 452 | version = "1.0.2" 453 | 454 | [[deps.NetworkOptions]] 455 | uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" 456 | version = "1.2.0" 457 | 458 | [[deps.Ogg_jll]] 459 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 460 | git-tree-sha1 = "887579a3eb005446d514ab7aeac5d1d027658b8f" 461 | uuid = "e7412a2a-1a6e-54c0-be00-318e2571c051" 462 | version = "1.3.5+1" 463 | 464 | [[deps.OpenBLAS_jll]] 465 | deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] 466 | uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" 467 | version = "0.3.21+4" 468 | 469 | [[deps.OpenLibm_jll]] 470 | deps = ["Artifacts", "Libdl"] 471 | uuid = "05823500-19ac-5b8b-9628-191a04bc5112" 472 | version = "0.8.1+0" 473 | 474 | [[deps.OpenSSL]] 475 | deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"] 476 | git-tree-sha1 = "51901a49222b09e3743c65b8847687ae5fc78eb2" 477 | uuid = "4d8831e6-92b7-49fb-bdf8-b643e874388c" 478 | version = "1.4.1" 479 | 480 | [[deps.OpenSSL_jll]] 481 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 482 | git-tree-sha1 = "9ff31d101d987eb9d66bd8b176ac7c277beccd09" 483 | uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" 484 | version = "1.1.20+0" 485 | 486 | [[deps.OpenSpecFun_jll]] 487 | deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] 488 | git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1" 489 | uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" 490 | version = "0.5.5+0" 491 | 492 | [[deps.Opus_jll]] 493 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 494 | git-tree-sha1 = "51a08fb14ec28da2ec7a927c4337e4332c2a4720" 495 | uuid = "91d4177d-7536-5919-b921-800302f37372" 496 | version = "1.3.2+0" 497 | 498 | [[deps.OrderedCollections]] 499 | git-tree-sha1 = "d321bf2de576bf25ec4d3e4360faca399afca282" 500 | uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" 501 | version = "1.6.0" 502 | 503 | [[deps.PCRE2_jll]] 504 | deps = ["Artifacts", "Libdl"] 505 | uuid = "efcefdf7-47ab-520b-bdef-62a2eaa19f15" 506 | version = "10.42.0+0" 507 | 508 | [[deps.Parsers]] 509 | deps = ["Dates", "PrecompileTools", "UUIDs"] 510 | git-tree-sha1 = "a5aef8d4a6e8d81f171b2bd4be5265b01384c74c" 511 | uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" 512 | version = "2.5.10" 513 | 514 | [[deps.Pipe]] 515 | git-tree-sha1 = "6842804e7867b115ca9de748a0cf6b364523c16d" 516 | uuid = "b98c9c47-44ae-5843-9183-064241ee97a0" 517 | version = "1.3.0" 518 | 519 | [[deps.Pixman_jll]] 520 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 521 | git-tree-sha1 = "b4f5d02549a10e20780a24fce72bea96b6329e29" 522 | uuid = "30392449-352a-5448-841d-b1acce4e97dc" 523 | version = "0.40.1+0" 524 | 525 | [[deps.Pkg]] 526 | deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] 527 | uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" 528 | version = "1.9.0" 529 | 530 | [[deps.PlotThemes]] 531 | deps = ["PlotUtils", "Statistics"] 532 | git-tree-sha1 = "1f03a2d339f42dca4a4da149c7e15e9b896ad899" 533 | uuid = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a" 534 | version = "3.1.0" 535 | 536 | [[deps.PlotUtils]] 537 | deps = ["ColorSchemes", "Colors", "Dates", "PrecompileTools", "Printf", "Random", "Reexport", "Statistics"] 538 | git-tree-sha1 = "f92e1315dadf8c46561fb9396e525f7200cdc227" 539 | uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043" 540 | version = "1.3.5" 541 | 542 | [[deps.Plots]] 543 | deps = ["Base64", "Contour", "Dates", "Downloads", "FFMPEG", "FixedPointNumbers", "GR", "JLFzf", "JSON", "LaTeXStrings", "Latexify", "LinearAlgebra", "Measures", "NaNMath", "Pkg", "PlotThemes", "PlotUtils", "PrecompileTools", "Preferences", "Printf", "REPL", "Random", "RecipesBase", "RecipesPipeline", "Reexport", "RelocatableFolders", "Requires", "Scratch", "Showoff", "SparseArrays", "Statistics", "StatsBase", "UUIDs", "UnicodeFun", "UnitfulLatexify", "Unzip"] 544 | git-tree-sha1 = "ad59edfb711a4751e0b8271454df47f84a47a29e" 545 | uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" 546 | version = "1.38.14" 547 | 548 | [deps.Plots.extensions] 549 | FileIOExt = "FileIO" 550 | GeometryBasicsExt = "GeometryBasics" 551 | IJuliaExt = "IJulia" 552 | ImageInTerminalExt = "ImageInTerminal" 553 | UnitfulExt = "Unitful" 554 | 555 | [deps.Plots.weakdeps] 556 | FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" 557 | GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" 558 | IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" 559 | ImageInTerminal = "d8c32880-2388-543b-8c61-d9f865259254" 560 | Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" 561 | 562 | [[deps.PrecompileTools]] 563 | deps = ["Preferences"] 564 | git-tree-sha1 = "259e206946c293698122f63e2b513a7c99a244e8" 565 | uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" 566 | version = "1.1.1" 567 | 568 | [[deps.Preferences]] 569 | deps = ["TOML"] 570 | git-tree-sha1 = "7eb1686b4f04b82f96ed7a4ea5890a4f0c7a09f1" 571 | uuid = "21216c6a-2e73-6563-6e65-726566657250" 572 | version = "1.4.0" 573 | 574 | [[deps.Printf]] 575 | deps = ["Unicode"] 576 | uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" 577 | 578 | [[deps.Qt5Base_jll]] 579 | deps = ["Artifacts", "CompilerSupportLibraries_jll", "Fontconfig_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "OpenSSL_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libxcb_jll", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_keysyms_jll", "Xorg_xcb_util_renderutil_jll", "Xorg_xcb_util_wm_jll", "Zlib_jll", "xkbcommon_jll"] 580 | git-tree-sha1 = "0c03844e2231e12fda4d0086fd7cbe4098ee8dc5" 581 | uuid = "ea2cea3b-5b76-57ae-a6ef-0a8af62496e1" 582 | version = "5.15.3+2" 583 | 584 | [[deps.REPL]] 585 | deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] 586 | uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" 587 | 588 | [[deps.Random]] 589 | deps = ["SHA", "Serialization"] 590 | uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" 591 | 592 | [[deps.RecipesBase]] 593 | deps = ["PrecompileTools"] 594 | git-tree-sha1 = "5c3d09cc4f31f5fc6af001c250bf1278733100ff" 595 | uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" 596 | version = "1.3.4" 597 | 598 | [[deps.RecipesPipeline]] 599 | deps = ["Dates", "NaNMath", "PlotUtils", "PrecompileTools", "RecipesBase"] 600 | git-tree-sha1 = "45cf9fd0ca5839d06ef333c8201714e888486342" 601 | uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" 602 | version = "0.6.12" 603 | 604 | [[deps.Reexport]] 605 | git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" 606 | uuid = "189a3867-3050-52da-a836-e630ba90ab69" 607 | version = "1.2.2" 608 | 609 | [[deps.RelocatableFolders]] 610 | deps = ["SHA", "Scratch"] 611 | git-tree-sha1 = "90bc7a7c96410424509e4263e277e43250c05691" 612 | uuid = "05181044-ff0b-4ac5-8273-598c1e38db00" 613 | version = "1.0.0" 614 | 615 | [[deps.Requires]] 616 | deps = ["UUIDs"] 617 | git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7" 618 | uuid = "ae029012-a4dd-5104-9daa-d747884805df" 619 | version = "1.3.0" 620 | 621 | [[deps.SHA]] 622 | uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" 623 | version = "0.7.0" 624 | 625 | [[deps.Scratch]] 626 | deps = ["Dates"] 627 | git-tree-sha1 = "30449ee12237627992a99d5e30ae63e4d78cd24a" 628 | uuid = "6c6a2e73-6563-6170-7368-637461726353" 629 | version = "1.2.0" 630 | 631 | [[deps.Serialization]] 632 | uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" 633 | 634 | [[deps.Showoff]] 635 | deps = ["Dates", "Grisu"] 636 | git-tree-sha1 = "91eddf657aca81df9ae6ceb20b959ae5653ad1de" 637 | uuid = "992d4aef-0814-514b-bc4d-f2e9a6c4116f" 638 | version = "1.0.3" 639 | 640 | [[deps.SimpleBufferStream]] 641 | git-tree-sha1 = "874e8867b33a00e784c8a7e4b60afe9e037b74e1" 642 | uuid = "777ac1f9-54b0-4bf8-805c-2214025038e7" 643 | version = "1.1.0" 644 | 645 | [[deps.Sockets]] 646 | uuid = "6462fe0b-24de-5631-8697-dd941f90decc" 647 | 648 | [[deps.SortingAlgorithms]] 649 | deps = ["DataStructures"] 650 | git-tree-sha1 = "a4ada03f999bd01b3a25dcaa30b2d929fe537e00" 651 | uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c" 652 | version = "1.1.0" 653 | 654 | [[deps.SparseArrays]] 655 | deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] 656 | uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" 657 | 658 | [[deps.SpecialFunctions]] 659 | deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] 660 | git-tree-sha1 = "ef28127915f4229c971eb43f3fc075dd3fe91880" 661 | uuid = "276daf66-3868-5448-9aa4-cd146d93841b" 662 | version = "2.2.0" 663 | 664 | [deps.SpecialFunctions.extensions] 665 | SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" 666 | 667 | [deps.SpecialFunctions.weakdeps] 668 | ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" 669 | 670 | [[deps.Statistics]] 671 | deps = ["LinearAlgebra", "SparseArrays"] 672 | uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" 673 | version = "1.9.0" 674 | 675 | [[deps.StatsAPI]] 676 | deps = ["LinearAlgebra"] 677 | git-tree-sha1 = "45a7769a04a3cf80da1c1c7c60caf932e6f4c9f7" 678 | uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" 679 | version = "1.6.0" 680 | 681 | [[deps.StatsBase]] 682 | deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] 683 | git-tree-sha1 = "75ebe04c5bed70b91614d684259b661c9e6274a4" 684 | uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" 685 | version = "0.34.0" 686 | 687 | [[deps.SuiteSparse_jll]] 688 | deps = ["Artifacts", "Libdl", "Pkg", "libblastrampoline_jll"] 689 | uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" 690 | version = "5.10.1+6" 691 | 692 | [[deps.TOML]] 693 | deps = ["Dates"] 694 | uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" 695 | version = "1.0.3" 696 | 697 | [[deps.Tar]] 698 | deps = ["ArgTools", "SHA"] 699 | uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" 700 | version = "1.10.0" 701 | 702 | [[deps.TensorCore]] 703 | deps = ["LinearAlgebra"] 704 | git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6" 705 | uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50" 706 | version = "0.1.1" 707 | 708 | [[deps.Test]] 709 | deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] 710 | uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" 711 | 712 | [[deps.TranscodingStreams]] 713 | deps = ["Random", "Test"] 714 | git-tree-sha1 = "9a6ae7ed916312b41236fcef7e0af564ef934769" 715 | uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" 716 | version = "0.9.13" 717 | 718 | [[deps.URIs]] 719 | git-tree-sha1 = "074f993b0ca030848b897beff716d93aca60f06a" 720 | uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" 721 | version = "1.4.2" 722 | 723 | [[deps.UUIDs]] 724 | deps = ["Random", "SHA"] 725 | uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" 726 | 727 | [[deps.Unicode]] 728 | uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" 729 | 730 | [[deps.UnicodeFun]] 731 | deps = ["REPL"] 732 | git-tree-sha1 = "53915e50200959667e78a92a418594b428dffddf" 733 | uuid = "1cfade01-22cf-5700-b092-accc4b62d6e1" 734 | version = "0.4.1" 735 | 736 | [[deps.Unitful]] 737 | deps = ["ConstructionBase", "Dates", "LinearAlgebra", "Random"] 738 | git-tree-sha1 = "ba4aa36b2d5c98d6ed1f149da916b3ba46527b2b" 739 | uuid = "1986cc42-f94f-5a68-af5c-568840ba703d" 740 | version = "1.14.0" 741 | 742 | [deps.Unitful.extensions] 743 | InverseFunctionsUnitfulExt = "InverseFunctions" 744 | 745 | [deps.Unitful.weakdeps] 746 | InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" 747 | 748 | [[deps.UnitfulLatexify]] 749 | deps = ["LaTeXStrings", "Latexify", "Unitful"] 750 | git-tree-sha1 = "e2d817cc500e960fdbafcf988ac8436ba3208bfd" 751 | uuid = "45397f5d-5981-4c77-b2b3-fc36d6e9b728" 752 | version = "1.6.3" 753 | 754 | [[deps.Unzip]] 755 | git-tree-sha1 = "ca0969166a028236229f63514992fc073799bb78" 756 | uuid = "41fe7b60-77ed-43a1-b4f0-825fd5a5650d" 757 | version = "0.2.0" 758 | 759 | [[deps.Wayland_jll]] 760 | deps = ["Artifacts", "Expat_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg", "XML2_jll"] 761 | git-tree-sha1 = "ed8d92d9774b077c53e1da50fd81a36af3744c1c" 762 | uuid = "a2964d1f-97da-50d4-b82a-358c7fce9d89" 763 | version = "1.21.0+0" 764 | 765 | [[deps.Wayland_protocols_jll]] 766 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 767 | git-tree-sha1 = "4528479aa01ee1b3b4cd0e6faef0e04cf16466da" 768 | uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91" 769 | version = "1.25.0+0" 770 | 771 | [[deps.XML2_jll]] 772 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "Zlib_jll"] 773 | git-tree-sha1 = "93c41695bc1c08c46c5899f4fe06d6ead504bb73" 774 | uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a" 775 | version = "2.10.3+0" 776 | 777 | [[deps.XSLT_jll]] 778 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgcrypt_jll", "Libgpg_error_jll", "Libiconv_jll", "Pkg", "XML2_jll", "Zlib_jll"] 779 | git-tree-sha1 = "91844873c4085240b95e795f692c4cec4d805f8a" 780 | uuid = "aed1982a-8fda-507f-9586-7b0439959a61" 781 | version = "1.1.34+0" 782 | 783 | [[deps.Xorg_libX11_jll]] 784 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll", "Xorg_xtrans_jll"] 785 | git-tree-sha1 = "5be649d550f3f4b95308bf0183b82e2582876527" 786 | uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc" 787 | version = "1.6.9+4" 788 | 789 | [[deps.Xorg_libXau_jll]] 790 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 791 | git-tree-sha1 = "4e490d5c960c314f33885790ed410ff3a94ce67e" 792 | uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec" 793 | version = "1.0.9+4" 794 | 795 | [[deps.Xorg_libXcursor_jll]] 796 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"] 797 | git-tree-sha1 = "12e0eb3bc634fa2080c1c37fccf56f7c22989afd" 798 | uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724" 799 | version = "1.2.0+4" 800 | 801 | [[deps.Xorg_libXdmcp_jll]] 802 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 803 | git-tree-sha1 = "4fe47bd2247248125c428978740e18a681372dd4" 804 | uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05" 805 | version = "1.1.3+4" 806 | 807 | [[deps.Xorg_libXext_jll]] 808 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"] 809 | git-tree-sha1 = "b7c0aa8c376b31e4852b360222848637f481f8c3" 810 | uuid = "1082639a-0dae-5f34-9b06-72781eeb8cb3" 811 | version = "1.3.4+4" 812 | 813 | [[deps.Xorg_libXfixes_jll]] 814 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"] 815 | git-tree-sha1 = "0e0dc7431e7a0587559f9294aeec269471c991a4" 816 | uuid = "d091e8ba-531a-589c-9de9-94069b037ed8" 817 | version = "5.0.3+4" 818 | 819 | [[deps.Xorg_libXi_jll]] 820 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXfixes_jll"] 821 | git-tree-sha1 = "89b52bc2160aadc84d707093930ef0bffa641246" 822 | uuid = "a51aa0fd-4e3c-5386-b890-e753decda492" 823 | version = "1.7.10+4" 824 | 825 | [[deps.Xorg_libXinerama_jll]] 826 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll"] 827 | git-tree-sha1 = "26be8b1c342929259317d8b9f7b53bf2bb73b123" 828 | uuid = "d1454406-59df-5ea1-beac-c340f2130bc3" 829 | version = "1.1.4+4" 830 | 831 | [[deps.Xorg_libXrandr_jll]] 832 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll"] 833 | git-tree-sha1 = "34cea83cb726fb58f325887bf0612c6b3fb17631" 834 | uuid = "ec84b674-ba8e-5d96-8ba1-2a689ba10484" 835 | version = "1.5.2+4" 836 | 837 | [[deps.Xorg_libXrender_jll]] 838 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"] 839 | git-tree-sha1 = "19560f30fd49f4d4efbe7002a1037f8c43d43b96" 840 | uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa" 841 | version = "0.9.10+4" 842 | 843 | [[deps.Xorg_libpthread_stubs_jll]] 844 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 845 | git-tree-sha1 = "6783737e45d3c59a4a4c4091f5f88cdcf0908cbb" 846 | uuid = "14d82f49-176c-5ed1-bb49-ad3f5cbd8c74" 847 | version = "0.1.0+3" 848 | 849 | [[deps.Xorg_libxcb_jll]] 850 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"] 851 | git-tree-sha1 = "daf17f441228e7a3833846cd048892861cff16d6" 852 | uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b" 853 | version = "1.13.0+3" 854 | 855 | [[deps.Xorg_libxkbfile_jll]] 856 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"] 857 | git-tree-sha1 = "926af861744212db0eb001d9e40b5d16292080b2" 858 | uuid = "cc61e674-0454-545c-8b26-ed2c68acab7a" 859 | version = "1.1.0+4" 860 | 861 | [[deps.Xorg_xcb_util_image_jll]] 862 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"] 863 | git-tree-sha1 = "0fab0a40349ba1cba2c1da699243396ff8e94b97" 864 | uuid = "12413925-8142-5f55-bb0e-6d7ca50bb09b" 865 | version = "0.4.0+1" 866 | 867 | [[deps.Xorg_xcb_util_jll]] 868 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll"] 869 | git-tree-sha1 = "e7fd7b2881fa2eaa72717420894d3938177862d1" 870 | uuid = "2def613f-5ad1-5310-b15b-b15d46f528f5" 871 | version = "0.4.0+1" 872 | 873 | [[deps.Xorg_xcb_util_keysyms_jll]] 874 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"] 875 | git-tree-sha1 = "d1151e2c45a544f32441a567d1690e701ec89b00" 876 | uuid = "975044d2-76e6-5fbe-bf08-97ce7c6574c7" 877 | version = "0.4.0+1" 878 | 879 | [[deps.Xorg_xcb_util_renderutil_jll]] 880 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"] 881 | git-tree-sha1 = "dfd7a8f38d4613b6a575253b3174dd991ca6183e" 882 | uuid = "0d47668e-0667-5a69-a72c-f761630bfb7e" 883 | version = "0.3.9+1" 884 | 885 | [[deps.Xorg_xcb_util_wm_jll]] 886 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"] 887 | git-tree-sha1 = "e78d10aab01a4a154142c5006ed44fd9e8e31b67" 888 | uuid = "c22f9ab0-d5fe-5066-847c-f4bb1cd4e361" 889 | version = "0.4.1+1" 890 | 891 | [[deps.Xorg_xkbcomp_jll]] 892 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxkbfile_jll"] 893 | git-tree-sha1 = "4bcbf660f6c2e714f87e960a171b119d06ee163b" 894 | uuid = "35661453-b289-5fab-8a00-3d9160c6a3a4" 895 | version = "1.4.2+4" 896 | 897 | [[deps.Xorg_xkeyboard_config_jll]] 898 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xkbcomp_jll"] 899 | git-tree-sha1 = "5c8424f8a67c3f2209646d4425f3d415fee5931d" 900 | uuid = "33bec58e-1273-512f-9401-5d533626f822" 901 | version = "2.27.0+4" 902 | 903 | [[deps.Xorg_xtrans_jll]] 904 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 905 | git-tree-sha1 = "79c31e7844f6ecf779705fbc12146eb190b7d845" 906 | uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10" 907 | version = "1.4.0+3" 908 | 909 | [[deps.Zlib_jll]] 910 | deps = ["Libdl"] 911 | uuid = "83775a58-1f1d-513f-b197-d71354ab007a" 912 | version = "1.2.13+0" 913 | 914 | [[deps.Zstd_jll]] 915 | deps = ["Artifacts", "JLLWrappers", "Libdl"] 916 | git-tree-sha1 = "49ce682769cd5de6c72dcf1b94ed7790cd08974c" 917 | uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" 918 | version = "1.5.5+0" 919 | 920 | [[deps.fzf_jll]] 921 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 922 | git-tree-sha1 = "868e669ccb12ba16eaf50cb2957ee2ff61261c56" 923 | uuid = "214eeab7-80f7-51ab-84ad-2988db7cef09" 924 | version = "0.29.0+0" 925 | 926 | [[deps.libaom_jll]] 927 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 928 | git-tree-sha1 = "3a2ea60308f0996d26f1e5354e10c24e9ef905d4" 929 | uuid = "a4ae2306-e953-59d6-aa16-d00cac43593b" 930 | version = "3.4.0+0" 931 | 932 | [[deps.libass_jll]] 933 | deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] 934 | git-tree-sha1 = "5982a94fcba20f02f42ace44b9894ee2b140fe47" 935 | uuid = "0ac62f75-1d6f-5e53-bd7c-93b484bb37c0" 936 | version = "0.15.1+0" 937 | 938 | [[deps.libblastrampoline_jll]] 939 | deps = ["Artifacts", "Libdl"] 940 | uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" 941 | version = "5.7.0+0" 942 | 943 | [[deps.libfdk_aac_jll]] 944 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 945 | git-tree-sha1 = "daacc84a041563f965be61859a36e17c4e4fcd55" 946 | uuid = "f638f0a6-7fb0-5443-88ba-1cc74229b280" 947 | version = "2.0.2+0" 948 | 949 | [[deps.libpng_jll]] 950 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] 951 | git-tree-sha1 = "94d180a6d2b5e55e447e2d27a29ed04fe79eb30c" 952 | uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f" 953 | version = "1.6.38+0" 954 | 955 | [[deps.libvorbis_jll]] 956 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Ogg_jll", "Pkg"] 957 | git-tree-sha1 = "b910cb81ef3fe6e78bf6acee440bda86fd6ae00c" 958 | uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a" 959 | version = "1.3.7+1" 960 | 961 | [[deps.nghttp2_jll]] 962 | deps = ["Artifacts", "Libdl"] 963 | uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" 964 | version = "1.48.0+0" 965 | 966 | [[deps.p7zip_jll]] 967 | deps = ["Artifacts", "Libdl"] 968 | uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" 969 | version = "17.4.0+0" 970 | 971 | [[deps.x264_jll]] 972 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 973 | git-tree-sha1 = "4fea590b89e6ec504593146bf8b988b2c00922b2" 974 | uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a" 975 | version = "2021.5.5+0" 976 | 977 | [[deps.x265_jll]] 978 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 979 | git-tree-sha1 = "ee567a171cce03570d77ad3a43e90218e38937a9" 980 | uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76" 981 | version = "3.5.0+0" 982 | 983 | [[deps.xkbcommon_jll]] 984 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll", "Wayland_protocols_jll", "Xorg_libxcb_jll", "Xorg_xkeyboard_config_jll"] 985 | git-tree-sha1 = "9ebfc140cc56e8c2156a15ceac2f0302e327ac0a" 986 | uuid = "d8fb68d0-12a3-5cfd-a85a-d49703b185fd" 987 | version = "1.4.1+0" 988 | -------------------------------------------------------------------------------- /Project.toml: -------------------------------------------------------------------------------- 1 | [deps] 2 | Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Computational Economics Notes 2 | 3 | These are notes written in Julia for the computational economics reading group. The notes can be found in the `notebooks` folder. 4 | 5 | There are probably many errors, all of which are my own. It is safe to say that everything is a work in progress 🚧 6 | 7 | ## Outline of topics 8 | 9 | 1. Floating point arithmetic -- **Complete** 10 | 2. Autodifferentiation and linear algebra -- **Complete** 11 | 3. Solutions to systems of linear equations -- **Incomplete** 12 | 4. Optimisation (unconstrained and constrained) -- **Complete** 13 | 5. Function approximation -- **Incomplete** 14 | 6. Dynamic programming (deterministic) -- **Incomplete** 15 | 7. Endogenous grid method (deterministic) -- **Empty** 16 | 8. Stochastic processes -- **Incomplete** 17 | 9. Simulation and random numbers **Incomplete** 18 | 10. Numerical integration -- **Empty** 19 | 11. Dynamic programming (stochastic) -- **Empty** 20 | 12. Endogenous grid method (stochastic) -- **Empty** 21 | 13. Perturbation methods -- **Empty** 22 | 14. Reiter's method -- **Empty** 23 | 15. Linear time iteration -- **Empty** 24 | 16. BKM algorithm -- **Empty** 25 | 17. Sequence space Jacobian -- **Empty** 26 | 18. Neural networks -- **Empty** 27 | 28 | We will probably not cover all topics during the year, but this is a first run. Future iterations will have more complete notes and include more topics. 29 | 30 | ## Resources 31 | 32 | Several resources were used in constructing these notes. I relied a lot on code from other people in setting up these notes. Below are links to some of the repositories, books and websites that I found helpful in trying to make sense of it all. These are not presented in any particular order. 33 | 34 | ### Repositories and websites 35 | 36 | 1. Fedor Ishkakov -- [Foundations of Computational Economics](https://github.com/fediskhakov/CompEcon) 37 | 2. Florian Oswald -- [Computational Economics for PhDs](https://github.com/floswald/NumericalMethods) 38 | 3. Ivan Rudik -- [Dynamic Optimization](https://github.com/AEM7130/class-repo) 39 | 4. Toby Driscoll -- [Fundamentals of Numerical Computaion](http://tobydriscoll.net/fnc-julia/frontmatter.html) 40 | 5. Chris Edmond -- [Macroeconomics PhD course](http://www.chrisedmond.net/phd2019.html) 41 | 6. Alisdair McKay -- [Numerical Analysis](https://github.com/amckay/EC702) 42 | 7. Stefano Pica -- [Macroeconomics PhD Course](https://github.com/stpica/EC702-Fall-TA) 43 | 8. QuantEcon -- [Quantitative Economics](https://quantecon.org/lectures/) 44 | 45 | ### Books 46 | 47 | ### Articles 48 | -------------------------------------------------------------------------------- /_research/wip/approximation/global/interpolation.md: -------------------------------------------------------------------------------- 1 | --- 2 | jupytext: 3 | cell_metadata_filter: -all 4 | formats: md:myst 5 | text_representation: 6 | extension: .md 7 | format_name: myst 8 | format_version: 0.13 9 | jupytext_version: 1.10.3 10 | kernelspec: 11 | display_name: Julia 1.6.1 12 | language: julia 13 | name: julia-fast 14 | --- 15 | 16 | ```{code-cell} 17 | :tags: [remove-cell] 18 | include("../init-notebook.jl") 19 | ``` 20 | 21 | (section-localapprox-interpolation)= 22 | # The interpolation problem 23 | 24 | ```{index} ! interpolation 25 | ``` 26 | 27 | :::{proof:definition} Interpolation problem 28 | Given $n+1$ distinct points $(t_0,y_0)$, $(t_1,y_1),\ldots,(t_n,y_n)$, with $t_0 53 | ``` 54 | 55 | ```{raw} latex 56 | %%start demo%% 57 | ``` 58 | 59 | Here are some points that we could consider to be observations of an unknown function on $[-1,1]$. 60 | 61 | ```{code-cell} 62 | n = 5 63 | t = range(-1,1,length=n+1) 64 | y = @. t^2 + t + 0.05*sin(20*t) 65 | 66 | scatter(t,y,label="data",leg=:top) 67 | ``` 68 | 69 | ```{index} ! Julia; fit 70 | ``` 71 | 72 | The polynomial interpolant, as computed using `fit`, looks very sensible. It's the kind of function you'd take home to meet your parents. 73 | 74 | ```{code-cell} 75 | p = Polynomials.fit(t,y,n) # interpolating polynomial 76 | plot!(p,-1,1,label="interpolant") 77 | ``` 78 | 79 | But now consider a different set of points generated in almost exactly the same way. 80 | 81 | ```{code-cell} 82 | n = 18 83 | t = range(-1,1,length=n+1) 84 | y = @. t^2 + t + 0.05*sin(20*t) 85 | 86 | scatter(t,y,label="data",leg=:top) 87 | ``` 88 | 89 | The points themselves are unremarkable. But take a look at what happens to the polynomial interpolant. 90 | 91 | ```{code-cell} 92 | p = Polynomials.fit(t,y,n) 93 | x = range(-1,1,length=1000) # use a lot of points 94 | plot!(x,p.(x),label="interpolant") 95 | ``` 96 | 97 | Surely there must be functions that are more intuitively representative of those points! 98 | ```{raw} html 99 | 100 | ``` 101 | 102 | ```{raw} latex 103 | %%end demo%% 104 | ``` 105 | 106 | 107 | ```{proof:observation} 108 | Interpolation by a polynomial at equally spaced nodes is ill-conditioned as the degree of the polynomial grows. 109 | ``` 110 | 111 | In Chapter 9 we explore the large oscillations in the last figure of {numref}`Demo %s `; it turns out that one must abandon either equally spaced nodes or $n\to\infty$ for polynomials. In the rest of this chapter we will instead keep $n$ fairly small and let the nodes be unrestricted. 112 | 113 | ## Piecewise polynomials 114 | 115 | ```{index} interpolation; by piecewise polynomials 116 | ``` 117 | 118 | In order to keep polynomial degrees small while interpolating large data sets, we will choose interpolants from the **piecewise polynomials**. Specifically, the interpolant $p$ must be a polynomial on each subinterval $[t_{k-1},t_k]$ for $k=1,\ldots,n$. 119 | 120 | ````{proof:example} 121 | Some examples of piecewise polynomials for the nodes $t_0=-2$, $t_1=0$, $t_2=1$, and $t_3=4$ are $p_1(x)=x+1$, $p_2(x)=\operatorname{sign}(x)$, $p_3(x)=|x-1|^{3}$, and $p_4(x)=(\max\{0,x\})^{4}$. Note that $p_{1}$, $p_{2}$, and $p_4$ would also be piecewise polynomial on the node set $\{t_0,t_1,t_3\}$, but $p_3$ would not. 122 | ```` 123 | 124 | Usually we designate in advance a maximum degree $d$ for each polynomial piece of $p(x)$. An important property of the piecewise polynomials of degree $d$ is that they form a vector space: that is, any linear combination of piecewise polynomials of degree $d$ is another piecewise polynomial of degree $d$. If $p$ and $q$ share the same node set, then the combination is piecewise polynomial on that node set. 125 | 126 | (demo-interpolation-pwise)= 127 | ```{proof:demo} 128 | ``` 129 | 130 | ```{raw} html 131 |
132 | ``` 133 | 134 | ```{raw} latex 135 | %%start demo%% 136 | ``` 137 | 138 | Let us recall the data from {numref}`Demo %s `. 139 | 140 | ```{code-cell} 141 | :tags: [hide-input] 142 | n = 12 143 | t = range(-1,1,length=n+1) 144 | y = @. t^2 + t + 0.5*sin(20*t) 145 | 146 | scatter(t,y,label="data",leg=:top) 147 | ``` 148 | 149 | Here is an interpolant that is linear between each consecutive pair of nodes, using `plinterp` from {numref}`section-localapprox-pwlin`. 150 | 151 | ```{code-cell} 152 | p = FNC.plinterp(t,y) 153 | plot!(p,-1,1,label="piecewise linear") 154 | ``` 155 | 156 | ```{index} ! Julia; Spline1D 157 | ``` 158 | 159 | We may prefer a smoother interpolant that is piecewise cubic, generated using `Spline1D` from the `Dierckx` package. 160 | 161 | ```{code-cell} 162 | p = Spline1D(t,y) 163 | plot!(x->p(x),-1,1,label="piecewise cubic") 164 | ``` 165 | ```{raw} html 166 |
167 | ``` 168 | 169 | ```{raw} latex 170 | %%end demo%% 171 | ``` 172 | 173 | We will consider piecewise linear interpolation in more detail in {numref}`section-localapprox-pwlin`, and we look at piecewise cubic interpolation in {numref}`section-localapprox-splines`. 174 | 175 | ## Conditioning of interpolation 176 | 177 | In the interpolation problem we are given the values $(t_k,y_k)$ for $k=0,\ldots,n$. Let us consider the nodes $t_k$ of the problem to be fixed, and let $a=t_0$, $b=t_n$. Then the data for the interpolation problem consists of a vector $\mathbf{y}$, and the result of the problem is a function on $[a,b]$. 178 | 179 | Let $\mathcal{I}$ be a prescription for producing the interpolant from a data vector. That is, $\mathcal{I}(\mathbf{y})=p$, where $p(t_k)=y_k$ for all $k$. The interpolation methods we will consider are all *linear*, in the sense that 180 | 181 | ```{math} 182 | :label: interp-linearity 183 | \cI(\alpha\mathbf{y} + \beta\mathbf{z}) = \alpha \cI(\mathbf{y}) + \beta \cI(\mathbf{z}) 184 | ``` 185 | 186 | for all vectors $\mathbf{y},\mathbf{z}$ and scalars $\alpha,\beta$. 187 | 188 | Linearity greatly simplifies the analysis of interpolation. To begin with, for any data vector $\mathbf{y}$ we have the standard expression $\mathbf{y}=\sum y_k \mathbf{e}_k$, where as always $\mathbf{e}_k$ is a column of an identity matrix.[^startzero] Hence by linearity, 189 | 190 | [^startzero]: To be precise, we are using $\mathbf{e}_k$ to mean column number $k+1$ from an $(n+1)\times (n+1)$ identity matrix, since in linear algebra we start indexing at 1. 191 | 192 | :::{math} 193 | :label: interp-cardinal1 194 | \cI( \mathbf{y} ) = \cI \left( \sum_{k=0}^n y_k \mathbf{e}_k \right) = \sum_{k=0}^n y_k \cI( \mathbf{e}_k ). 195 | ::: 196 | 197 | The functions appearing within the sum above have particular significance. 198 | 199 | ```{index} ! cardinal function 200 | ``` 201 | 202 | ::::{proof:definition} Cardinal function 203 | A **cardinal function** $\phi_k$ for a node set $t_0,\ldots,t_n$ is the function that interpolates the value $(t_k,1)$ and $(t_j,0)$ for all $j\neq k$. 204 | :::: 205 | 206 | For any set of $n+1$ nodes, there are $n+1$ cardinal functions $\phi_0,\ldots,\phi_n$, each singling out a different interpolation node in the set. We finish {eq}`interp-cardinal1` by writing 207 | 208 | :::{math} 209 | :label: interp-cardinal2 210 | \cI( \mathbf{y} ) = \sum_{k=0}^n y_k \phi_k. 211 | ::: 212 | 213 | In the following result we use the function infinity-norm or max-norm defined by 214 | 215 | ```{math} 216 | :label: norm-function-inf 217 | \| f\|_{\infty} = \max_{x \in [a,b]} |f(x)|. 218 | ``` 219 | 220 | ```{index} condition number; of interpolation 221 | ``` 222 | 223 | (theorem-interp-conditioning)= 224 | ````{proof:theorem} Conditioning of interpolation 225 | Suppose that $\cI$ is a linear interpolation method on nodes $t_0,\ldots,t_n$. Then with respect to the infinity norm, the absolute condition number of $\cI$ satisfies 226 | 227 | ```{math} 228 | :label: interp-conditioning 229 | \max_{0\le k \le n}\, \bigl\| \phi_k \bigr\|_\infty \le \kappa(\mathbf{y}) \le \sum_{k=0}^n \, \bigl\| \phi_k \bigr\|_\infty, 230 | ``` 231 | 232 | where the $\phi_k$ are cardinal interpolating functions. 233 | ```` 234 | 235 | ::::{proof:proof} 236 | Suppose the data vector is perturbed from $\mathbf{y}$ to $\mathbf{y}+ \boldsymbol{\delta}$. Then 237 | 238 | ```{math} 239 | :label: lininterp-perturb 240 | \cI(\mathbf{y} + \boldsymbol{\delta}) - \cI(\mathbf{y}) = \cI(\boldsymbol{\delta}) = \sum_{k=0}^n \delta_k \phi_k. 241 | ``` 242 | 243 | Hence 244 | 245 | ```{math} 246 | \frac{\bigl\|\cI(\mathbf{y} + \boldsymbol{\delta}) - \cI(\mathbf{y}) \bigr\|_{\infty}}{\| \boldsymbol{\delta} \|_{\infty}} = 247 | \left\|\, \sum_{k=0}^{n} \frac{\delta_k}{\|\boldsymbol{\delta} \|_{\infty}} \phi_k \, \right\|_{\infty}. 248 | ``` 249 | 250 | The absolute condition number maximizes this quantity over all $\boldsymbol{\delta}$. Suppose $j$ is such that $\|\phi_j\|$ is maximal. Then let $\boldsymbol{\delta}=\mathbf{e}_j$ and the first inequality in {eq}`interp-conditioning` follows. The other inequality follows from the triangle inequality: 251 | 252 | $$ 253 | \left\| \, \sum_{k=0}^{n} \frac{\delta_k}{\|\boldsymbol{\delta} \|_{\infty}} \phi_k \, \right\|_{\infty} \le \sum_{k=0}^{n} \frac{|\delta_k|}{\|\boldsymbol{\delta} \|_{\infty}} \| \phi_k \|_\infty. 254 | $$ 255 | 256 | Since $|\delta_k|\le \|\boldsymbol{\delta}\|_\infty$ for all $k$, this finishes {eq}`interp-conditioning`. 257 | :::: 258 | 259 | (demo-interp-cond)= 260 | ```{proof:demo} 261 | ``` 262 | 263 | ```{raw} html 264 |
265 | ``` 266 | 267 | ```{raw} latex 268 | %%start demo%% 269 | ``` 270 | 271 | In {numref}`Demo %s ` and {numref}`Demo %s ` we saw a big difference between polynomial interpolation and piecewise polynomial interpolation of some arbitrarily chosen data. The same effects can be seen clearly in the cardinal functions, which are closely tied to the condition numbers. 272 | 273 | ```{code-cell} 274 | n = 18 275 | t = range(-1,stop=1,length=n+1) 276 | y = [zeros(9);1;zeros(n-9)]; # data for 10th cardinal function 277 | 278 | scatter(t,y,label="data") 279 | ``` 280 | 281 | ```{code-cell} 282 | ϕ = Spline1D(t,y) 283 | plot!(x->ϕ(x),-1,1,label="spline", 284 | xlabel=L"x", ylabel=L"\phi(x)", title="Piecewise cubic cardinal function") 285 | ``` 286 | 287 | The piecewise cubic cardinal function is nowhere greater than one in absolute value. This happens to be true for all the cardinal functions, ensuring a good condition number for any interpolation with these functions. But the story for global polynomials is very different. 288 | 289 | ```{code-cell} 290 | scatter(t,y,label="data") 291 | 292 | ϕ = Polynomials.fit(t,y,n) 293 | plot!(x->ϕ(x),-1,1,label="polynomial", 294 | xlabel=L"x", ylabel=L"\phi(x)", title="Polynomial cardinal function") 295 | ``` 296 | 297 | From the figure we can see that the condition number for polynomial interpolation on these nodes is at least 500. 298 | ```{raw} html 299 |
300 | ``` 301 | 302 | ```{raw} latex 303 | %%end demo%% 304 | ``` 305 | 306 | ## Exercises 307 | 308 | 1. ⌨ Create data by entering 309 | 310 | ``` julia 311 | t = -2:4; y = tanh.(t); 312 | ``` 313 | 314 | **(a)** Use `fit` to construct and plot the polynomial interpolant of the data, superimposed on a scatter plot of the data. 315 | 316 | **(b)** Use `Spline1D` to construct and plot a piecewise cubic interpolant of the data, superimposed on a scatter plot of the data. 317 | 318 | 2. ⌨ The following table gives the life expectancy in the U.S. by year of birth. 319 | 320 | | 1980 | 1985 | 1990 | 1995 | 2000 | 2005 | 2010 | 321 | |:---:|:----:|:-----:|:----:|:----:|:----:|:----:| 322 | | 73.7 | 74.7 | 75.4 | 75.8 | 77.0 | 77.8 | 78.7 | 323 | 324 | **(a)** Defining "year since 1980" as the independent variable, use `fit` to construct and plot the polynomial interpolant of the data. 325 | 326 | **(b)** Use `Spline1D` to construct and plot a piecewise cubic interpolant of the data. 327 | 328 | **(c)** Use both methods to estimate the life expectancy for a person born in 2007. Which value is more believable? 329 | 330 | 3. ⌨ The following two vectors define a flying saucer shape. 331 | 332 | ``` julia 333 | x = [ 0,0.51,0.96,1.06,1.29,1.55,1.73,2.13,2.61, 334 | 2.19,1.76,1.56,1.25,1.04,0.58,0 ] 335 | y = [ 0,0.16,0.16,0.43,0.62,0.48,0.19,0.18,0, 336 | -0.12,-0.12,-0.29,-0.30,-0.15,-0.16,0 ] 337 | ``` 338 | We can regard both $x$ and $y$ as functions of a parameter $s$, with the points being values given at $s=0,1,\ldots,15$. 339 | 340 | **(a)** Use `Spline1D` once on each coordinate as functions of $s$, and make a picture of the flying saucer. 341 | 342 | **(b)** One drawback of the result in part (a) is the noticeable corner at the left side, which corresponds to $s=0$ from above and $s=15$ from below. There is a periodic variation on cubic spline interpolation that you can invoke by adding the keyword `periodic=true` to the `Spline1D` call. Use this to re-plot the flying saucer. 343 | 344 | (problem-quadratic-interpolant)= 345 | 4. ✍ Define 346 | 347 | ```{math} 348 | q(s) = a\frac{s(s-1)}{2} - b (s-1)(s+1) + c \frac{s(s+1)}{2}. 349 | ``` 350 | 351 | **(a)** Show that $q$ is a polynomial interpolant of the points $(-1,a)$, $(0,b)$, $(1,c)$. 352 | 353 | **(b)** Find a change of variable $s=Ax+B$ so that the values $s=-1,0,1$ correspond to $x=x_0-h,x_0,x_0+h$. 354 | 355 | **(c)** Find a quadratic polynomial interpolant $\tilde{q}(x)$ for the points $(x_0-h,a)$, $(x_0,b)$, $(x_0+h,c)$. 356 | 357 | 5. ✍ (continuation) Use the result of the previous exercise and {numref}`Theorem %s ` to derive bounds on the condition number of quadratic polynomial interpolation at the nodes $x_0-h$, $x_0$, $x_0+h$. 358 | 359 | 360 | -------------------------------------------------------------------------------- /_research/wip/approximation/local/conditioning-poly.jl: -------------------------------------------------------------------------------- 1 | 2 | # Poor conditioning in polynomial interpolation 3 | 4 | using LinearAlgebra 5 | using Plots 6 | using Polynomials 7 | 8 | n = 5 9 | t = LinRange(-1, 1, n + 1) 10 | y = @. t^2 + t + 0.05 * sin(20 * t) # using the broadcast operator across all the different operations. Don't alway like doing this, but here it seems to cut down on typing... Biggest issue is with sin.(20 .* t). 11 | 12 | scatter(t, y, label="data", leg=:top) 13 | 14 | ## We can use polyfit to get a polynomial interpolant 15 | 16 | p = fit(t, y, n) 17 | plot!(p, -1, 1, label="interpolant") # This polynomial fits the points really well... 18 | 19 | # However, if we fit a different set of points then the story changes a bit 20 | 21 | n = 18 22 | t = LinRange(-1, 1, n + 1) 23 | y = @. t^2 + t + 0.05 * sin(20 * t) 24 | 25 | scatter(t, y, m=:o, l=nothing, label="data", leg=:top) 26 | 27 | p = fit(t, y, n) 28 | x = LinRange(-1, 1, 1000) # use a lot of points 29 | plot!(x, p.(x), label="interpolant") # polynomial interpolant is a terrible fit in this case! -------------------------------------------------------------------------------- /_research/wip/approximation/local/piecewise-poly.jl: -------------------------------------------------------------------------------- 1 | 2 | # Piecewise polynomial interpolation 3 | 4 | using Interpolations 5 | using LinearAlgebra 6 | using Plots 7 | using Polynomials 8 | 9 | n = 12 10 | t = LinRange(-1,1,n+1) 11 | y = @. t^2 + t + 0.5*sin(20*t) 12 | 13 | scatter(t,y,label="data",leg=:top) 14 | 15 | p = LinearInterpolation(t,y) # One option is to have linear interpolation 16 | plot!(x->p(x),-1,1,label="piecewise linear") 17 | 18 | p = CubicSplineInterpolation(t,y) # Alternatively one could have a interpolant that is piecewise cubic 19 | plot!(x->p(x),-1,1,label="piecewise cubic") -------------------------------------------------------------------------------- /_research/wip/discrete-dp/value-function-iteration/caraiani-vfi.jl: -------------------------------------------------------------------------------- 1 | 2 | using Parameters 3 | 4 | ## Implementation of the value function algorithm. Follows the work of Collard. Optimal growth model with a CRRA utility function and law of motion provided for capital. 5 | 6 | # This is an easy implementation, perhaps one of the simplest out of all that I have read. There are other methods, this one is just quite easy to understand 7 | 8 | ## Start by specifying the parameters 9 | 10 | @with_kw struct params 11 | 12 | # parameter specification 13 | σ = 1.5 # utility parameter 14 | δ = 0.1 # depreciation rate 15 | β = 0.95 # discount factor 16 | α = 0.30 # capital elasticity of output 17 | 18 | # steady state 19 | ks = ((1 - β * (1 - δ)) / (α * β)) ^ (1 / (α - 1)) 20 | 21 | # grid construction 22 | nbk = 1000 # Number of grid points 23 | dev = 0.9 # Maximal deviation from the steady state 24 | kmin = (1 - dev) * ks # Lower bound on the grid 25 | kmax = (1 + dev) * ks # Upper bound on the grid 26 | 27 | p = params() 28 | 29 | function cara_vfi() 30 | @unpack σ, δ, β, α, dev, nbk, kmin, kmax = p 31 | 32 | csy = (1 - α * β * δ) / (1 - β * (1 - δ)) 33 | devk = (kmax - kmin) / (nbk - 1) 34 | 35 | k = collect(range(kmin, kmax, step = nbk)) # Alternatively one could write k = collect(kmin:nbk:kmax) 36 | 37 | end 38 | 39 | 40 | -------------------------------------------------------------------------------- /_research/wip/discrete-dp/value-function-iteration/edmond-vfi.jl: -------------------------------------------------------------------------------- 1 | 2 | using LinearAlgebra 3 | using Parameters 4 | 5 | # Value function iteration 6 | # This is basically just a port of the MATLAB code. Trying to understand the basic ideas. 7 | # Setup of the model parameters 8 | 9 | @with_kw struct params 10 | # basic parameters 11 | α = 1/3 # Capital share in production function 12 | β = 0.95 # Time discount factor 13 | δ = 0.05 # Depreciation rate 14 | σ = 1. # CRRA (=1/IES) 15 | ρ = (1/β) - 1 # This is the implied rate of time preference 16 | 17 | # grid construction 18 | max_iter = 500 # Maximum number of iterations 19 | tol = 1e-7 # Numbers smaller than this are treated as zero 20 | penalty = 10^16 # Penalises constraint violations (will have to think about this) 21 | n = 1001 # Number of nodes for `k` grid 22 | 23 | # steady state 24 | kstar = (α/(ρ .+ δ))^(1/(1 .- α)) # Steady state Value 25 | kbar = (1/δ)^(1/(1 .- α)) 26 | end 27 | 28 | p = params() 29 | 30 | function ed_vfi() 31 | @unpack α, β, δ, σ, ρ, max_iter, tol, penalty, n, kstar, kbar = p 32 | 33 | # Components for the grid of capital stock 34 | kmin = tol # Lower bound for `k` 35 | kmax = kbar # Upper bound for `k` 36 | 37 | k = LinRange(kmin, kmax, n) |> collect # These area linearly spaced, but we need to choose the grid better / more carefully. 38 | 39 | c = zeros(n, n) # This is a nxn matrix that contains only zeros. 40 | 41 | # The for loop works at this point. Just need to figure out what it is doing. 42 | for j in 1:n 43 | c[:, j] = k.^α .+ (1 .- δ) .* k .- k[j] 44 | end 45 | 46 | # This for loop leads to some infeasible choices, so we need to enforce feasibility. We will do this by penalising violations of the feasibility constraint. This section needs some work. 47 | 48 | violations = [c .<= 0] 49 | c = c[c .> 0] .+ eps() 50 | 51 | if σ == 1. 52 | u = log.(c) .- (penalty .* violations[1]); 53 | else 54 | u = (1 ./(1 .- σ))*(c.^(1 .- σ) .- 1) .- (penalty .* violations); 55 | end 56 | 57 | # Solve the Bellman equation by value function iteration 58 | v = zeros(n, 1) 59 | 60 | for i = 1:max_iter 61 | RHS = u .+ β .* kron(ones(n, 1), v') 62 | 63 | 64 | 65 | end -------------------------------------------------------------------------------- /_research/wip/discrete-dp/value-function-iteration/edmond_vfi_collocation.jl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DawievLill/CompEconNotes/926dd86c9ec1e7e1f1d39ac894162c60d00110dc/_research/wip/discrete-dp/value-function-iteration/edmond_vfi_collocation.jl -------------------------------------------------------------------------------- /_research/wip/discrete-dp/value-function-iteration/fedor-vfi.jl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DawievLill/CompEconNotes/926dd86c9ec1e7e1f1d39ac894162c60d00110dc/_research/wip/discrete-dp/value-function-iteration/fedor-vfi.jl -------------------------------------------------------------------------------- /_research/wip/discrete-dp/value-function-iteration/florian-vfi.jl: -------------------------------------------------------------------------------- 1 | 2 | # Example of discrete value function iteration for a deterministic growth model, similar to optimal growth or cake eating problem 3 | 4 | # Start by setting parameters in the parameter block 5 | 6 | using LinearAlgebra 7 | using Optim 8 | using Parameters 9 | using Roots 10 | 11 | @with_kw struct params 12 | α::Float64 = 0.65 13 | β::Float64 = 0.95 14 | grid_max::Int64 = 2 # This is going to be an upper bound on the state variable 15 | n::Int64 = 150 # Number of grid points 16 | N_iter::Int64 = 3000 # Number of iterations 17 | 18 | end 19 | 20 | 21 | kgrid::Float64 = 1e-2:(grid_max - 1e-2)/(n-1):grid_max # Represents the equispaced grid. There are other ways to choose the grid points, which we will see later when we talk about function approximation methods, see the notes of Rudik. 22 | 23 | -------------------------------------------------------------------------------- /_research/wip/discrete-dp/value-function-iteration/mccandless-vfi.jl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DawievLill/CompEconNotes/926dd86c9ec1e7e1f1d39ac894162c60d00110dc/_research/wip/discrete-dp/value-function-iteration/mccandless-vfi.jl -------------------------------------------------------------------------------- /_research/wip/discrete-dp/value-function-iteration/rudik-vfi.jl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DawievLill/CompEconNotes/926dd86c9ec1e7e1f1d39ac894162c60d00110dc/_research/wip/discrete-dp/value-function-iteration/rudik-vfi.jl -------------------------------------------------------------------------------- /_research/wip/optimisation/bracketing/bracket_min.jl: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Bracketing -- Wheeler - p 36 4 | 5 | using Parameters 6 | 7 | @with_kw struct params 8 | s::Float64 = 1e-2 9 | k::Float64 = 2.0 10 | end 11 | 12 | p = params() 13 | 14 | function bracket_minimum(f, x) 15 | @unpack s, k = p 16 | 17 | a, ya = x, f(x) 18 | b, yb = a + s, f(a + s) 19 | 20 | if yb > ya 21 | a, b = b, a 22 | ya, yb = yb, ya 23 | s = -s 24 | end 25 | 26 | while true 27 | x, yc = b + s, f(b + s) 28 | if yc > yb 29 | return a < c ? (a, c) : (c, a) 30 | end 31 | a, ya, b, yb = b, yb, c, yc 32 | s *= k 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /_research/wip/optimisation/bracketing/fibonacci_search.jl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | function fibonacci_search(f, a, b, n; ϵ=0.01) 6 | 7 | s = (1 - √5)/(1 + √5) 8 | ρ = 1 / (φ * (1 - s^(n + 1))/(1 - s^n)) 9 | d = ρ * b + (1 - ρ) * a 10 | yd = f(d) 11 | 12 | for i in 1 : n-1 13 | if i == n-1 14 | c = ϵ * a + (1 - ϵ) * d 15 | else 16 | c = ρ * a + (1 - ρ) * b 17 | end 18 | yc = f(c) 19 | if yc < yd 20 | b, d, yd = d, c, yc 21 | else 22 | a, b = b, c 23 | end 24 | ρ = 1 / (φ * (1 - s^(n - i + 1))/(1 - s^(n - i))) 25 | end 26 | 27 | return a < b ? (a, b) : (b, a) 28 | 29 | end 30 | -------------------------------------------------------------------------------- /_research/wip/optimisation/derivatives/symbolic_diff.jl: -------------------------------------------------------------------------------- 1 | 2 | # Wheeler - p21 (Derivatives) 3 | 4 | # Limit equation defining the derivative can be presented in three different ways, forward difference, central difference and backward difference 5 | 6 | # If the function can be represented symbolically we can use symbolic differentiation via the SymEngine package in Julia -- Sympy in python. 7 | 8 | using SymEngine 9 | 10 | @vars x; # This defines x as a symbolic variable 11 | f = x^2 + x/2 - sin(x)/x; 12 | diff(f, x) # Symbolic differentiation -------------------------------------------------------------------------------- /_research/wip/optimisation/direct/nelder-mead.jl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DawievLill/CompEconNotes/926dd86c9ec1e7e1f1d39ac894162c60d00110dc/_research/wip/optimisation/direct/nelder-mead.jl -------------------------------------------------------------------------------- /_research/wip/optimisation/gradient/gradient-descent.jl: -------------------------------------------------------------------------------- 1 | 2 | # Gradient descent method 3 | 4 | # Code for this can be found at https://nicoguaro.github.io/posts/numerical-06/ and at https://shuvomoy.github.io/blog/programming/2020/04/10/Implementing_simple_gradient_descent_Julia.html 5 | 6 | # The ideas are nicely explained in Wheeler. I am assuming that there will be millions of different ways of coding this. 7 | 8 | using LinearAlgebra 9 | using Parameters 10 | using ProximalOperators 11 | using Optim 12 | 13 | @with_kw struct params 14 | niter::Float64 = 50 15 | gtol::Float64 = 1e-8 16 | end 17 | 18 | p = params() 19 | 20 | # Think about how this algorithm works in particular 21 | function grad_descent(f, ∇f, x) 22 | @unpack niter, gtol = p 23 | 24 | g_old = ∇f(x) 25 | γ = 0.1 # This is the step size 26 | 27 | for cont = 1:niter 28 | 29 | dx = -γ * g_old 30 | x = x + dx 31 | g = ∇f(x) 32 | 33 | dg = g - g_old 34 | g_old = g 35 | 36 | γ = dx' * dg / (dg' * dg) 37 | 38 | if norm(g) < gtol 39 | break 40 | end 41 | end 42 | return x, f(x) 43 | end 44 | 45 | 46 | function rosen(x) 47 | return (1 - x[1])^2 + 100*(x[2] - x[1]^2)^2 48 | end 49 | 50 | 51 | function rosen_grad(x) 52 | return [-2*(1 - x[1]) - 400*x[1]*(x[2] - x[1]^2); 53 | 200*(x[2] - x[1]^2)] 54 | end 55 | 56 | 57 | println(grad_descent(rosen, rosen_grad, [2.0, 1.0])) 58 | 59 | 60 | # One nice way to approach this is using Optim.jl 61 | 62 | 63 | # Put a pin in this last method below, I don't know much about proximal operators. 64 | 65 | ## An alternative method, which seems more comprehensive. Try and follow along with the logic. 66 | 67 | # For this problem we will be creating types in Julia 68 | 69 | struct GD_problem{F <: ProximableFunction, A <: AbstractVecOrMat{<:Real}, R <: Real} 70 | 71 | # This is the problem structure that contains information regarding the specific gradient descent problem at hand. 72 | 73 | f::F # Our objective function is a Proximable Function types 74 | x0::A # The initial condition is of type Vector or Matrix with real entries 75 | γ::R # The stepsize is a real value 76 | 77 | end 78 | 79 | # Example for the usage of this struct. If you want to solve least squares problem. 80 | 81 | A = randn(6, 5) 82 | b = randn(6) 83 | m, n = size(A) 84 | 85 | x0 = randn(n) 86 | f = LeastSquares(A, b) 87 | γ = 1.0 88 | 89 | problem = GD_problem(f, x0, γ) 90 | -------------------------------------------------------------------------------- /_research/wip/optimisation/local-descent/line-search.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Line search from local descent chapter 3 | 4 | @author: Dawie van Lill 5 | 6 | @date: 2020-11-09 7 | 8 | References 9 | ---------- 10 | Algorithms for Optimisation 11 | 12 | =# 13 | 14 | using LineSearches 15 | using Optim 16 | 17 | function bracket_minimum(f, x=0; s=1e-2, k=2.0) 18 | a, ya = x, f(x) 19 | b, yb = a + s, f(a + s) 20 | 21 | if yb > ya 22 | a, b = b, a 23 | ya, yb = yb, ya 24 | s = -s 25 | end 26 | 27 | while true 28 | c, yc = b + s, f(b + s) 29 | if yc > yb 30 | return a < c ? (a, c) : (c, a) 31 | end 32 | a, ya, b, yb = b, yb, c, yc 33 | s *= k 34 | end 35 | end 36 | 37 | function bracket_sign_change(f′, a, b; k=2) 38 | if a > b; a,b = b,a; end # ensure a < b 39 | center, half_width = (b+a)/2, (b-a)/2 40 | 41 | while f′(a)*f′(b) > 0 42 | half_width *= ka 43 | a = center - half_width 44 | b = center + half_width 45 | end 46 | 47 | return (a,b) 48 | end 49 | 50 | 51 | function line_search(f, x, d) 52 | objective = α -> f(x + α * d) 53 | a, b = bracket_minimum(objective) 54 | α = bracket_sign_change(objective, a, b) 55 | 56 | return x + α * d 57 | end 58 | 59 | ## One can use the LineSearches package in Julia 60 | -------------------------------------------------------------------------------- /_research/wip/quadrature/basics.jl: -------------------------------------------------------------------------------- 1 | 2 | # Basic integration techniques in Julia 3 | 4 | using Plots 5 | using QuadGK 6 | 7 | exact = exp(1) - 1 # provides the exact solution to the problem. 8 | 9 | Q, errest = quadgk(x -> exp(x), 0, 1) 10 | @show Q # The result from this package is exactly the same as the exact solution 11 | 12 | # However, numerical integration can easily be applied to function that do not provide analytical solutions. 13 | 14 | Q,errest = quadgk(x -> exp(sin(x)), 0, 1) 15 | @show Q 16 | 17 | plot([exp,x->exp(sin(x))],0,1,fill=0,leg=:none, 18 | ylabel=["exp(x)" "exp(sin(x))"],ylim=[0,2.7],layout=(2,1)) 19 | -------------------------------------------------------------------------------- /_research/wip/quadrature/trapezoid.jl: -------------------------------------------------------------------------------- 1 | 2 | # Newton-Cotes trapezoid 3 | 4 | """ 5 | trapezoid(f,a,b,n) 6 | 7 | Apply the trapezoid integration formula for integrand `f` over interval [`a`,`b`], broken up into `n` equal pieces. Returns estimate, vector of nodes, and vector of integrand values at the nodes. 8 | """ 9 | function trapezoid(f,a,b,n) 10 | h = (b-a)/n 11 | t = LinRange(a,b,n+1) 12 | y = f.(t) 13 | T = h * ( sum(y[2:n]) + 0.5*(y[1] + y[n+1]) ) 14 | 15 | return T, t, y 16 | end -------------------------------------------------------------------------------- /_research/wip/root-finding/multivariate/broyden.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Broyden's method 3 | 4 | @author: Dawie van Lill 5 | 6 | @date: 2020-10-27 7 | 8 | References 9 | ---------- 10 | Fundamentals of numerical computation 11 | https://nicoguaro.github.io/posts/numerical-05/#disqus_thread 12 | 13 | 14 | Should be quite close to Newton's method 15 | =# 16 | 17 | using LinearAlgebra 18 | using Parameters 19 | 20 | @with_kw struct params 21 | maxiter::Int64 = 50 22 | tol::Float64 = 1000 * eps() 23 | xtol::Float64 = 1000 * eps() 24 | end 25 | 26 | p = params() 27 | 28 | """ 29 | broyden(f, jac, x) 30 | 31 | Use Broyden's method to find a root of a system of equations, starting from `x`. The functions `f` and `jac' should return the residual vector and the Jacobian matrix, respectively. Returns history of root estimates as a vector of vectors. 32 | """ 33 | function broyden(f, jac, x) 34 | @unpack maxiter, tol, xtol = p 35 | 36 | x = [float(x)] 37 | y, J = f(x), jac(x) # At this stage this gives the function and the Jacobian (which can be determined manually, or via ForwardDiff) 38 | dx = Inf 39 | k = 1 40 | 41 | # The norm is used instead of the absolute value 42 | while (norm(dx) > xtol) && (norm(y) > tol) && (k < maxiter) 43 | 44 | dx = -J\y 45 | push!(x, x[k] .+ dx) 46 | k += 1 47 | y = f(x[k]) 48 | 49 | # Need to figure this step out 50 | df = y .- 51 | J = jac(x[k]) .+ (df .- jac(x[k]) .* dx) .* dx' / (dx' .* dx) 52 | end 53 | return x 54 | end 55 | 56 | function nlfun(x) 57 | 58 | f = zeros(3) 59 | f[1] = exp(x[2]-x[1]) - 2; 60 | f[2] = x[1]*x[2] + x[3]; 61 | f[3] = x[2]*x[3] + x[1]^2 - x[2]; 62 | return f 63 | 64 | end 65 | 66 | # Jacobian is manually calculated here. There should be a way to do this automatically. 67 | function nljac(x) 68 | 69 | J = zeros(3,3) 70 | J[1,:] = [-exp(x[2]-x[1]),exp(x[2]-x[1]), 0] 71 | J[2,:] = [x[2], x[1], 1] 72 | J[3,:] = [2*x[1], x[3]-1, x[2]] 73 | return J 74 | 75 | end 76 | 77 | x = [0,0,0] 78 | y = broyden(nlfun, nljac, x) 79 | 80 | -------------------------------------------------------------------------------- /_research/wip/root-finding/multivariate/levenberg.jl: -------------------------------------------------------------------------------- 1 | 2 | # Quasi-Newton iteration to find the root. 3 | 4 | """ 5 | fdjac(f,x0,y0) 6 | 7 | Compute a finite-difference approximation of the Jacobian matrix for `f` at `x0`, where `y0`=`f(x0)` is given. 8 | """ 9 | function fdjac(f,x0,y0) 10 | 11 | delta = sqrt(eps()) # FD step size 12 | m, n = length(y0), length(x0) 13 | 14 | if n == 1 15 | J = (f(x0 + delta) - y0) / delta 16 | else 17 | J = zeros(m,n) 18 | In = I(n) 19 | for j = 1:n 20 | J[:,j] = (f(x0 + delta * In[:,j]) - y0) / delta 21 | end 22 | end 23 | 24 | return J 25 | end 26 | 27 | """ 28 | levenberg(f,x1,tol) 29 | 30 | Use Levenberg's quasi-Newton iteration to find a root of the system `f`, starting from `x1`, with `tol` as the stopping tolerance in both step size and residual norm. Returns root estimates as a matrix, one estimate per column. 31 | """ 32 | function levenberg(f,x1,tol=1e-12) 33 | 34 | # Operating parameters. 35 | ftol = tol; xtol = tol; maxiter = 40; 36 | 37 | x = zeros(length(x1),maxiter) 38 | x = [float(x1)] 39 | fk = f(x1) 40 | k = 1; s = Inf; 41 | Ak = fdjac(f,x1,fk) # start with FD Jacobian 42 | jac_is_new = true 43 | 44 | lambda = 10; 45 | while (norm(s) > xtol) && (norm(fk) > ftol) && (k < maxiter) 46 | # Compute the proposed step. 47 | B = Ak'*Ak + lambda*I 48 | z = Ak'*fk 49 | s = -(B\z) 50 | 51 | xnew = x[k] + s 52 | fnew = f(xnew) 53 | 54 | # Do we accept the result? 55 | if norm(fnew) < norm(fk) # accept 56 | y = fnew - fk 57 | push!(x,xnew) 58 | fk = fnew 59 | k += 1 60 | 61 | lambda = lambda/10 # get closer to Newton 62 | # Broyden update of the Jacobian. 63 | Ak = Ak + (y-Ak*s)*(s'/(s'*s)) 64 | jac_is_new = false 65 | else # don't accept 66 | # Get closer to steepest descent. 67 | lambda = 4lambda 68 | # Re-initialize the Jacobian if it's out of date. 69 | if !jac_is_new 70 | Ak = fdjac(f,x[k],fk) 71 | jac_is_new = true 72 | end 73 | end 74 | end 75 | 76 | if (norm(fk) > 1e-3) 77 | @warn "Iteration did not find a root." 78 | end 79 | 80 | return x 81 | end -------------------------------------------------------------------------------- /_research/wip/root-finding/multivariate/newton_mv.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Newton's method (multivariate case) 3 | 4 | @author: Dawie van Lill 5 | 6 | @date: 2020-10-27 7 | 8 | References 9 | ---------- 10 | Fundamentals of numerical computation 11 | 12 | =# 13 | 14 | using Calculus 15 | using LinearAlgebra 16 | using Parameters 17 | 18 | @with_kw struct params 19 | tol::Float64 = 1000 * eps() 20 | xtol::Float64 = 1000 * eps() 21 | maxiter::Int64 = 40 22 | end 23 | 24 | p = params() 25 | 26 | """ 27 | newtonsys(f,jac,x1) 28 | 29 | Use Newton's method to find a root of a system of equations, 30 | starting from `x1`. The functions `f` and `jac should return the 31 | residual vector and the Jacobian matrix, respectively. Returns 32 | history of root estimates as a vector of vectors. 33 | """ 34 | function newtonsys(f, jac, x1) 35 | @unpack tol, xtol, maxiter = p 36 | 37 | x = [float(x1)] # Convert to float since the eventual output will most likely be floating point 38 | y, J = f(x1), jac(x1) 39 | dx = Inf 40 | k = 1 41 | 42 | # The norm is used instead of the absolute value 43 | while (norm(dx) > xtol) && (norm(y) > tol) && (k < maxiter) 44 | 45 | dx = -(J\y) # Newton step uses backslash 46 | push!(x, x[k] + dx) 47 | k += 1 48 | y, J = f(x[k]), jac(x[k]) 49 | end 50 | return x 51 | end 52 | 53 | # Looks incredibly similar to the univariate case. This is a nice feature of Julia, the fact that it is vector-friendly. 54 | 55 | # Example 56 | 57 | function nlfun(x) 58 | f = zeros(3) 59 | f[1] = exp(x[2]-x[1]) - 2; 60 | f[2] = x[1]*x[2] + x[3]; 61 | f[3] = x[2]*x[3] + x[1]^2 - x[2]; 62 | return f 63 | end 64 | 65 | # Jacobian is manually calculated here. There should be a way to do this automatically. 66 | function nljac(x) 67 | J = zeros(3,3) 68 | J[1,:] = [-exp(x[2]-x[1]),exp(x[2]-x[1]), 0] 69 | J[2,:] = [x[2], x[1], 1] 70 | J[3,:] = [2*x[1], x[3]-1, x[2]] 71 | return J 72 | end 73 | 74 | x1 = [0,0,0] 75 | x = newtonsys(nlfun,nljac,x1) 76 | 77 | 78 | 79 | # Another way to code this from Caraiani / Collard 80 | 81 | # function newton_calaiardi(f) 82 | 83 | # maxit = 1000 84 | # tol = 1e-5 85 | 86 | # x0 = [1.0; 1.0] 87 | # y0 = reshape(collect(f(x0[1], x0[2])), 2, 1) 88 | 89 | # gr1 = Calculus.gradient() 90 | 91 | # end -------------------------------------------------------------------------------- /_research/wip/root-finding/multivariate/nl_least_squares.jl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DawievLill/CompEconNotes/926dd86c9ec1e7e1f1d39ac894162c60d00110dc/_research/wip/root-finding/multivariate/nl_least_squares.jl -------------------------------------------------------------------------------- /_research/wip/root-finding/univariate/bisection.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Bisection algorithm 3 | 4 | @author: Dawie van Lill 5 | 6 | @date: 2020-10-27 7 | 8 | References 9 | ---------- 10 | Wheeler - Algorithms for Optimisation p49 11 | Miranda and Fackler -- Applied Computational Economics and Finance p33 12 | 13 | =# 14 | 15 | using BenchmarkTools 16 | using Parameters 17 | using Roots 18 | 19 | @with_kw struct params 20 | tol::Float64 = 1e-18 21 | end 22 | 23 | f = x -> x^3 - 2; 24 | p = params() 25 | 26 | # Bisection algorithm as presented in Miranda and Fackler 27 | function fackler_bisection(f, a, b) 28 | @unpack tol = p 29 | 30 | s = sign(f(a)) 31 | x = (a + b) / 2 # Guess for the value of x -- mean of the interval 32 | d = (b - a) / 2 # Initial difference between bounds 33 | 34 | while d > tol 35 | d = d/2 36 | 37 | if s == sign(f(x)) 38 | x = x + d 39 | else 40 | x = x - d 41 | end 42 | end 43 | print("The root of f(x) is at $x") 44 | end 45 | 46 | ## Example 47 | fackler_bisection(f, 1, 2) # This should give a value of about 1.25992105 48 | 49 | # This algorithm gives us a bracket that contains the root 50 | function wheeler_bisection(f, a, b) 51 | @unpack tol = p 52 | 53 | # Interesting way in which an if statement can be phrased in one line 54 | if a > b; a, b = b, a; end # This ensures that a < b 55 | 56 | ya, yb = f(a), f(b) 57 | 58 | if ya == 0; b = a; end 59 | if yb == 0; a = b; end 60 | 61 | while b - a > tol 62 | x = (a + b) / 2 63 | y = f(x) 64 | 65 | if y == 0 66 | a, b = x, x 67 | elseif sign(y) == sign(ya) 68 | a = x 69 | else 70 | b = x 71 | end 72 | 73 | end 74 | return (a, b) 75 | end 76 | 77 | ## Example 78 | wheeler_bisection(f, 1, 2) # This should give a value of about (1.2599210441112518, 1.2599210515618324) 79 | 80 | # There is a package in Julia called roots, that uses something like a bisection algorithm. In fact, you can go look at the code https://github.com/JuliaMath/Roots.jl/blob/master/src/bracketing.jl 81 | 82 | # It is worthwhile looking at the code to see how software engineers will code something like this. The general rule is that if there is a package out there to that does things efficiently, do not try and code it up yourself. Use existing software. 83 | 84 | find_zero(f, (1, 2), Bisection()) 85 | 86 | @btime wheeler_bisection(f, 1, 2) 87 | @btime fackler_bisection(f, 1, 2) 88 | @btime find_zero(f, (1, 2), Bisection()) 89 | 90 | # Comparison of times actually shows that the find_zero method is slowest... It could be that the tolerance is quite high (greater precision). -------------------------------------------------------------------------------- /_research/wip/root-finding/univariate/fp_iteration.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Fixed point (function) iteration (univariate case) 3 | 4 | @author: Dawie van Lill 5 | 6 | @date: 2020-10-27 7 | 8 | References 9 | ---------- 10 | Fundamentals of numerical computation 11 | https://github.com/AEM7130/spring-2020 12 | 13 | =# 14 | 15 | using LinearAlgebra 16 | 17 | # Example 18 | 19 | f = x -> x^(-0.5) 20 | 21 | function rudik_iteration(f, guess) 22 | 23 | tol = 1e-3 24 | x_old = guess 25 | 26 | x = 1e-10 27 | difference = 1e10 28 | 29 | @time while abs(difference) > tol 30 | 31 | x = f(x_old) 32 | difference = x - x_old 33 | x_old = x 34 | end 35 | 36 | print("Fixed point of f(x) is at $x") 37 | 38 | end 39 | 40 | ## Fix this code, it doesn't seem to run at this stage. 41 | 42 | function caraiani_iteration(f, guess) 43 | 44 | tol = 1e-3 45 | maxiter = 1000 46 | 47 | for i = 1:maxiter 48 | if norm(f(guess) - guess) < tol 49 | return 50 | end 51 | guess = f(guess) 52 | end 53 | guess 54 | end 55 | 56 | -------------------------------------------------------------------------------- /_research/wip/root-finding/univariate/newton.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Newtons method for scalar root finding 3 | 4 | @author: Dawie van Lill 5 | 6 | @date: 2020-10-27 7 | 8 | References 9 | ---------- 10 | Fundamentals of numerical computation 11 | 12 | =# 13 | 14 | using ForwardDiff 15 | using Parameters 16 | using Roots 17 | 18 | @with_kw struct params 19 | funtol::Float64 = 100 * eps() 20 | xtol::Float64 = 100 * eps() 21 | maxiter::Int64 = 40 22 | end 23 | 24 | p = params() 25 | 26 | """ 27 | newton(f, dfdx, x1) 28 | 29 | Use Newton's method to find a root of `f` starting from `x1`, where `dfdx` is the derivative of `f`. This returns a vector of root estimates. 30 | """ 31 | function newton(f, dfdx, x1) 32 | @unpack funtol, xtol, maxiter = p 33 | 34 | x = [x1] # This puts the `x1` value into an array 35 | y = f(x1) # This is for a specifically defined input function 36 | dx = Inf # For the initial pass -- think about This 37 | k = 1 38 | 39 | while (abs(dx) > xtol) && (abs(y) > funtol) && (k < maxiter) 40 | 41 | dydx = dfdx(x[k]) 42 | dx = -y/dydx # This is referred to as the Newton step 43 | push!(x, x[k] + dx) # Amend this array by adding the adjusted Newton step value 44 | 45 | k += 1 # Increment k by one (next iteration) 46 | y = f(x[k]) # Function evaluation at the next value of the iteration 47 | 48 | end 49 | 50 | if k == maxiter 51 | @warn "Maximum number of iterations reached" 52 | end 53 | return x 54 | end 55 | 56 | # Example 57 | 58 | f(x) = exp(x) - x - 2; # Our function that we want to evaluate 59 | dfdx(x) = exp(x) - 1; # We can also determine this with AD of symbolic differentiation. 60 | x = newton(f, dfdx, 1.0); 61 | # println(x[end]) # Provide us with the value for the root 62 | 63 | 64 | # There is an implementation of Newton's method using the Roots.jl package and also ForwardDiff to find the derivative 65 | 66 | D(f) = x -> ForwardDiff.derivative(f, float(x)) 67 | @time find_zero((f, D(f)), 1.0, Roots.Newton()) -------------------------------------------------------------------------------- /_research/wip/root-finding/univariate/secant.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Quasi-Newton (secant) method for scalar root finding 3 | 4 | @author: Dawie van Lill 5 | 6 | @date: 2020-10-27 7 | 8 | References 9 | ---------- 10 | Fundamentals of numerical computation 11 | Collard notes 12 | 13 | =# 14 | 15 | using Parameters 16 | 17 | @with_kw struct params 18 | tol::Float64 = 100 * eps() 19 | xtol::Float64 = 100 * eps() 20 | maxiter::Int64 = 40 21 | end 22 | 23 | p = params() 24 | 25 | """ 26 | secant(f, x1, x2) 27 | 28 | Use the secant method to find a root of `f` starting from `x1` and `x2`. Returns a vector of root estimates. 29 | """ 30 | function secant(f, x1, x2) 31 | @unpack tol, xtol, maxiter = p 32 | 33 | x = [x1, x2] 34 | y1 = f(x1) 35 | y2 = 100 36 | dx = Inf 37 | k = 2 38 | 39 | while (abs(dx) > xtol) && (abs(y2) > tol) && (k < maxiter) 40 | 41 | y2 = f(x[k]) 42 | dx = -y2 * (x[k] - x[k-1]) / (y2 - y1) # This is the secant step 43 | push!(x, x[k] + dx) 44 | 45 | k += 1 46 | y1 = y2 47 | 48 | end 49 | return x 50 | end 51 | 52 | # The code for the above secant function is almost identical to the newton code. 53 | 54 | # Example 55 | 56 | f = x -> exp(x) - x - 2; # Our function that we want to evaluate 57 | #dfdx = x -> exp(x) - 1; # We can also determine this with AD of symbolic differentiation. 58 | x = secant(f, 1.0, 2.0); 59 | print(x[end]) # Provide us with the value for the root 60 | 61 | # Another way to potentially approach this problem is the following. However, I don't think the coding is as generic (or elegant as the previous approach) 62 | 63 | # function caraiani_secant(f, x_0, x_1) 64 | 65 | # tol = 1e-3 66 | # err = 1.0 67 | 68 | # while err > 0 69 | 70 | # d = (-f(x_1) * (x_1 - x_0))/(f(x_1) - f(x_0)) 71 | # x = x_1 + d 72 | 73 | # err = abs(x - x_1) - tol * (1 + abs(x)) 74 | 75 | # x_0 = x_1 76 | # x_1 = x 77 | 78 | # end 79 | # return x, f(x) 80 | # end 81 | 82 | -------------------------------------------------------------------------------- /notebooks/topic-10.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.19.9 3 | 4 | using Markdown 5 | using InteractiveUtils 6 | 7 | # ╔═╡ 6af35ec0-296a-11ed-13c1-45a6a0209c97 8 | begin 9 | using Distributions 10 | using LinearAlgebra 11 | end 12 | 13 | # ╔═╡ d415c38f-c9bc-4b5a-bda1-93c5d7cfb5ce 14 | md" # Introduction to Markov chains " 15 | 16 | # ╔═╡ 177d3703-7e24-4371-a026-f1163356513f 17 | md" Many of the workhorse models of economics contain Markov chains, so this is a topic that is worth studing in and of itself. All the dynamic models that we will work with in future will make use of finite Markov chains in some way. 18 | 19 | In particular, when we deal with autoregressive processes Markov chains are going to be a very important tool that we can use. As we will see in the next session, when we want to discretise income processes, we will make use of Markov chains. " 20 | 21 | # ╔═╡ c076a455-61b8-447a-9343-6e40995beb4c 22 | md" ## Introduction " 23 | 24 | # ╔═╡ d3bbec37-1160-4f40-8219-3444ce5b3ffd 25 | md" Consider a process that has a value each time period. 26 | 27 | We have that $X_t$ is its value in period $t$. 28 | 29 | We want to construct a probability model for the sequence of successive values $X_0, X_1, \ldots$. 30 | 31 | Simplest case is where the $X_t$ values are independent random variables. However, this is not always possible. There is likely some degree of dependence on past values. If we consider something like the process for income over time it is likely that your current income is in some way dependent on past income. 32 | 33 | In other words, it is reasonable to assume that the conditional distribution of $X_{t+1}$ given the entire history of the series in question $X_t, X_{t-1}, \ldots X_0$ depends on these past values only through the value at time period $t$. 34 | 35 | This memorylessness assumption is what defines a Markov chain. 36 | 37 | We reiterate, the Markov property states that the probability distribiution over $X_{t+1}$ depends only on $X_t$ and not on any other values of the process. 38 | 39 | A Markov chain is a type of **stochastic process**. 40 | 41 | **Stochastic processes** are mathematical objects that describe the evolution of random variables in time. One can write this stochastic process as, 42 | 43 | $$\{X_t\}_{t \in T}$$ 44 | 45 | We will work with the particular case where the stochastic process can take on a finite or countable number of possible values. 46 | 47 | To quickly summarise then, 48 | 49 | - Markov process: stochastic process with the Markov property 50 | - Finite Markov chain: special case of the Markov process 51 | 52 | Now let us move to a more formal description of finite Markov chains. 53 | 54 | " 55 | 56 | # ╔═╡ 55483c46-a7a1-4450-8ddb-8d928a0b7c31 57 | md" ### Finite Markov chains " 58 | 59 | # ╔═╡ 84544b3e-6d19-4ca5-8af7-8df4e5352061 60 | md" ## Stochastic matrices " 61 | 62 | # ╔═╡ 00000000-0000-0000-0000-000000000001 63 | PLUTO_PROJECT_TOML_CONTENTS = """ 64 | [deps] 65 | Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" 66 | LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 67 | 68 | [compat] 69 | Distributions = "~0.25.68" 70 | """ 71 | 72 | # ╔═╡ 00000000-0000-0000-0000-000000000002 73 | PLUTO_MANIFEST_TOML_CONTENTS = """ 74 | # This file is machine-generated - editing it directly is not advised 75 | 76 | julia_version = "1.7.3" 77 | manifest_format = "2.0" 78 | 79 | [[deps.ArgTools]] 80 | uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" 81 | 82 | [[deps.Artifacts]] 83 | uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" 84 | 85 | [[deps.Base64]] 86 | uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" 87 | 88 | [[deps.Calculus]] 89 | deps = ["LinearAlgebra"] 90 | git-tree-sha1 = "f641eb0a4f00c343bbc32346e1217b86f3ce9dad" 91 | uuid = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9" 92 | version = "0.5.1" 93 | 94 | [[deps.ChainRulesCore]] 95 | deps = ["Compat", "LinearAlgebra", "SparseArrays"] 96 | git-tree-sha1 = "80ca332f6dcb2508adba68f22f551adb2d00a624" 97 | uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" 98 | version = "1.15.3" 99 | 100 | [[deps.ChangesOfVariables]] 101 | deps = ["ChainRulesCore", "LinearAlgebra", "Test"] 102 | git-tree-sha1 = "38f7a08f19d8810338d4f5085211c7dfa5d5bdd8" 103 | uuid = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0" 104 | version = "0.1.4" 105 | 106 | [[deps.Compat]] 107 | deps = ["Dates", "LinearAlgebra", "UUIDs"] 108 | git-tree-sha1 = "5856d3031cdb1f3b2b6340dfdc66b6d9a149a374" 109 | uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" 110 | version = "4.2.0" 111 | 112 | [[deps.CompilerSupportLibraries_jll]] 113 | deps = ["Artifacts", "Libdl"] 114 | uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" 115 | 116 | [[deps.DataAPI]] 117 | git-tree-sha1 = "fb5f5316dd3fd4c5e7c30a24d50643b73e37cd40" 118 | uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" 119 | version = "1.10.0" 120 | 121 | [[deps.DataStructures]] 122 | deps = ["Compat", "InteractiveUtils", "OrderedCollections"] 123 | git-tree-sha1 = "d1fff3a548102f48987a52a2e0d114fa97d730f0" 124 | uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" 125 | version = "0.18.13" 126 | 127 | [[deps.Dates]] 128 | deps = ["Printf"] 129 | uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" 130 | 131 | [[deps.DensityInterface]] 132 | deps = ["InverseFunctions", "Test"] 133 | git-tree-sha1 = "80c3e8639e3353e5d2912fb3a1916b8455e2494b" 134 | uuid = "b429d917-457f-4dbc-8f4c-0cc954292b1d" 135 | version = "0.4.0" 136 | 137 | [[deps.Distributions]] 138 | deps = ["ChainRulesCore", "DensityInterface", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SparseArrays", "SpecialFunctions", "Statistics", "StatsBase", "StatsFuns", "Test"] 139 | git-tree-sha1 = "334a5896c1534bb1aa7aa2a642d30ba7707357ef" 140 | uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" 141 | version = "0.25.68" 142 | 143 | [[deps.DocStringExtensions]] 144 | deps = ["LibGit2"] 145 | git-tree-sha1 = "5158c2b41018c5f7eb1470d558127ac274eca0c9" 146 | uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" 147 | version = "0.9.1" 148 | 149 | [[deps.Downloads]] 150 | deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] 151 | uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" 152 | 153 | [[deps.DualNumbers]] 154 | deps = ["Calculus", "NaNMath", "SpecialFunctions"] 155 | git-tree-sha1 = "5837a837389fccf076445fce071c8ddaea35a566" 156 | uuid = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74" 157 | version = "0.6.8" 158 | 159 | [[deps.FileWatching]] 160 | uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" 161 | 162 | [[deps.FillArrays]] 163 | deps = ["LinearAlgebra", "Random", "SparseArrays", "Statistics"] 164 | git-tree-sha1 = "3399bbad4c9e9a2fd372a54d7b67b3c7121b6402" 165 | uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" 166 | version = "0.13.3" 167 | 168 | [[deps.HypergeometricFunctions]] 169 | deps = ["DualNumbers", "LinearAlgebra", "OpenLibm_jll", "SpecialFunctions", "Test"] 170 | git-tree-sha1 = "709d864e3ed6e3545230601f94e11ebc65994641" 171 | uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a" 172 | version = "0.3.11" 173 | 174 | [[deps.InteractiveUtils]] 175 | deps = ["Markdown"] 176 | uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" 177 | 178 | [[deps.InverseFunctions]] 179 | deps = ["Test"] 180 | git-tree-sha1 = "b3364212fb5d870f724876ffcd34dd8ec6d98918" 181 | uuid = "3587e190-3f89-42d0-90ee-14403ec27112" 182 | version = "0.1.7" 183 | 184 | [[deps.IrrationalConstants]] 185 | git-tree-sha1 = "7fd44fd4ff43fc60815f8e764c0f352b83c49151" 186 | uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" 187 | version = "0.1.1" 188 | 189 | [[deps.JLLWrappers]] 190 | deps = ["Preferences"] 191 | git-tree-sha1 = "abc9885a7ca2052a736a600f7fa66209f96506e1" 192 | uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" 193 | version = "1.4.1" 194 | 195 | [[deps.LibCURL]] 196 | deps = ["LibCURL_jll", "MozillaCACerts_jll"] 197 | uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" 198 | 199 | [[deps.LibCURL_jll]] 200 | deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] 201 | uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" 202 | 203 | [[deps.LibGit2]] 204 | deps = ["Base64", "NetworkOptions", "Printf", "SHA"] 205 | uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" 206 | 207 | [[deps.LibSSH2_jll]] 208 | deps = ["Artifacts", "Libdl", "MbedTLS_jll"] 209 | uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" 210 | 211 | [[deps.Libdl]] 212 | uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" 213 | 214 | [[deps.LinearAlgebra]] 215 | deps = ["Libdl", "libblastrampoline_jll"] 216 | uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 217 | 218 | [[deps.LogExpFunctions]] 219 | deps = ["ChainRulesCore", "ChangesOfVariables", "DocStringExtensions", "InverseFunctions", "IrrationalConstants", "LinearAlgebra"] 220 | git-tree-sha1 = "94d9c52ca447e23eac0c0f074effbcd38830deb5" 221 | uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" 222 | version = "0.3.18" 223 | 224 | [[deps.Logging]] 225 | uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" 226 | 227 | [[deps.Markdown]] 228 | deps = ["Base64"] 229 | uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" 230 | 231 | [[deps.MbedTLS_jll]] 232 | deps = ["Artifacts", "Libdl"] 233 | uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" 234 | 235 | [[deps.Missings]] 236 | deps = ["DataAPI"] 237 | git-tree-sha1 = "bf210ce90b6c9eed32d25dbcae1ebc565df2687f" 238 | uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28" 239 | version = "1.0.2" 240 | 241 | [[deps.MozillaCACerts_jll]] 242 | uuid = "14a3606d-f60d-562e-9121-12d972cd8159" 243 | 244 | [[deps.NaNMath]] 245 | deps = ["OpenLibm_jll"] 246 | git-tree-sha1 = "a7c3d1da1189a1c2fe843a3bfa04d18d20eb3211" 247 | uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" 248 | version = "1.0.1" 249 | 250 | [[deps.NetworkOptions]] 251 | uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" 252 | 253 | [[deps.OpenBLAS_jll]] 254 | deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] 255 | uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" 256 | 257 | [[deps.OpenLibm_jll]] 258 | deps = ["Artifacts", "Libdl"] 259 | uuid = "05823500-19ac-5b8b-9628-191a04bc5112" 260 | 261 | [[deps.OpenSpecFun_jll]] 262 | deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] 263 | git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1" 264 | uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" 265 | version = "0.5.5+0" 266 | 267 | [[deps.OrderedCollections]] 268 | git-tree-sha1 = "85f8e6578bf1f9ee0d11e7bb1b1456435479d47c" 269 | uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" 270 | version = "1.4.1" 271 | 272 | [[deps.PDMats]] 273 | deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"] 274 | git-tree-sha1 = "cf494dca75a69712a72b80bc48f59dcf3dea63ec" 275 | uuid = "90014a1f-27ba-587c-ab20-58faa44d9150" 276 | version = "0.11.16" 277 | 278 | [[deps.Pkg]] 279 | deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] 280 | uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" 281 | 282 | [[deps.Preferences]] 283 | deps = ["TOML"] 284 | git-tree-sha1 = "47e5f437cc0e7ef2ce8406ce1e7e24d44915f88d" 285 | uuid = "21216c6a-2e73-6563-6e65-726566657250" 286 | version = "1.3.0" 287 | 288 | [[deps.Printf]] 289 | deps = ["Unicode"] 290 | uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" 291 | 292 | [[deps.QuadGK]] 293 | deps = ["DataStructures", "LinearAlgebra"] 294 | git-tree-sha1 = "3c009334f45dfd546a16a57960a821a1a023d241" 295 | uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc" 296 | version = "2.5.0" 297 | 298 | [[deps.REPL]] 299 | deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] 300 | uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" 301 | 302 | [[deps.Random]] 303 | deps = ["SHA", "Serialization"] 304 | uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" 305 | 306 | [[deps.Reexport]] 307 | git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" 308 | uuid = "189a3867-3050-52da-a836-e630ba90ab69" 309 | version = "1.2.2" 310 | 311 | [[deps.Rmath]] 312 | deps = ["Random", "Rmath_jll"] 313 | git-tree-sha1 = "bf3188feca147ce108c76ad82c2792c57abe7b1f" 314 | uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa" 315 | version = "0.7.0" 316 | 317 | [[deps.Rmath_jll]] 318 | deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] 319 | git-tree-sha1 = "68db32dff12bb6127bac73c209881191bf0efbb7" 320 | uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f" 321 | version = "0.3.0+0" 322 | 323 | [[deps.SHA]] 324 | uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" 325 | 326 | [[deps.Serialization]] 327 | uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" 328 | 329 | [[deps.Sockets]] 330 | uuid = "6462fe0b-24de-5631-8697-dd941f90decc" 331 | 332 | [[deps.SortingAlgorithms]] 333 | deps = ["DataStructures"] 334 | git-tree-sha1 = "b3363d7460f7d098ca0912c69b082f75625d7508" 335 | uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c" 336 | version = "1.0.1" 337 | 338 | [[deps.SparseArrays]] 339 | deps = ["LinearAlgebra", "Random"] 340 | uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" 341 | 342 | [[deps.SpecialFunctions]] 343 | deps = ["ChainRulesCore", "IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] 344 | git-tree-sha1 = "d75bda01f8c31ebb72df80a46c88b25d1c79c56d" 345 | uuid = "276daf66-3868-5448-9aa4-cd146d93841b" 346 | version = "2.1.7" 347 | 348 | [[deps.Statistics]] 349 | deps = ["LinearAlgebra", "SparseArrays"] 350 | uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" 351 | 352 | [[deps.StatsAPI]] 353 | deps = ["LinearAlgebra"] 354 | git-tree-sha1 = "f9af7f195fb13589dd2e2d57fdb401717d2eb1f6" 355 | uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" 356 | version = "1.5.0" 357 | 358 | [[deps.StatsBase]] 359 | deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] 360 | git-tree-sha1 = "d1bf48bfcc554a3761a133fe3a9bb01488e06916" 361 | uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" 362 | version = "0.33.21" 363 | 364 | [[deps.StatsFuns]] 365 | deps = ["ChainRulesCore", "HypergeometricFunctions", "InverseFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"] 366 | git-tree-sha1 = "5783b877201a82fc0014cbf381e7e6eb130473a4" 367 | uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c" 368 | version = "1.0.1" 369 | 370 | [[deps.SuiteSparse]] 371 | deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"] 372 | uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" 373 | 374 | [[deps.TOML]] 375 | deps = ["Dates"] 376 | uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" 377 | 378 | [[deps.Tar]] 379 | deps = ["ArgTools", "SHA"] 380 | uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" 381 | 382 | [[deps.Test]] 383 | deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] 384 | uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" 385 | 386 | [[deps.UUIDs]] 387 | deps = ["Random", "SHA"] 388 | uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" 389 | 390 | [[deps.Unicode]] 391 | uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" 392 | 393 | [[deps.Zlib_jll]] 394 | deps = ["Libdl"] 395 | uuid = "83775a58-1f1d-513f-b197-d71354ab007a" 396 | 397 | [[deps.libblastrampoline_jll]] 398 | deps = ["Artifacts", "Libdl", "OpenBLAS_jll"] 399 | uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" 400 | 401 | [[deps.nghttp2_jll]] 402 | deps = ["Artifacts", "Libdl"] 403 | uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" 404 | 405 | [[deps.p7zip_jll]] 406 | deps = ["Artifacts", "Libdl"] 407 | uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" 408 | """ 409 | 410 | # ╔═╡ Cell order: 411 | # ╠═6af35ec0-296a-11ed-13c1-45a6a0209c97 412 | # ╟─d415c38f-c9bc-4b5a-bda1-93c5d7cfb5ce 413 | # ╟─177d3703-7e24-4371-a026-f1163356513f 414 | # ╟─c076a455-61b8-447a-9343-6e40995beb4c 415 | # ╟─d3bbec37-1160-4f40-8219-3444ce5b3ffd 416 | # ╟─55483c46-a7a1-4450-8ddb-8d928a0b7c31 417 | # ╟─84544b3e-6d19-4ca5-8af7-8df4e5352061 418 | # ╟─00000000-0000-0000-0000-000000000001 419 | # ╟─00000000-0000-0000-0000-000000000002 420 | -------------------------------------------------------------------------------- /notebooks/topic-2.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.19.9 3 | 4 | using Markdown 5 | using InteractiveUtils 6 | 7 | # This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). 8 | macro bind(def, element) 9 | quote 10 | local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end 11 | local el = $(esc(element)) 12 | global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) 13 | el 14 | end 15 | end 16 | 17 | # ╔═╡ 1c7f7f74-7c57-11eb-293a-d1be483a7ca0 18 | begin 19 | import Pkg 20 | Pkg.activate(mktempdir()) 21 | Pkg.add([ 22 | Pkg.PackageSpec(name="Images"), 23 | Pkg.PackageSpec(name="ImageMagick"), 24 | Pkg.PackageSpec(name="PlutoUI"), 25 | Pkg.PackageSpec(name="HypertextLiteral"), 26 | Pkg.PackageSpec(name="ForwardDiff"), 27 | Pkg.PackageSpec(name="SymEngine"), 28 | Pkg.PackageSpec(name="Plots"), 29 | Pkg.PackageSpec(name="GR"), 30 | Pkg.PackageSpec(name="Zygote"), 31 | Pkg.PackageSpec(name="FiniteDifferences"), 32 | ]) 33 | using Images 34 | using PlutoUI 35 | using HypertextLiteral 36 | using LinearAlgebra 37 | using ForwardDiff # Automatic differentiation 38 | using SymEngine # Symbolic differentiation 39 | using GR # Graphics 40 | using Zygote # Reverse mode automatic differentiation 41 | using FiniteDifferences # Finite differences 42 | end 43 | 44 | # ╔═╡ 7819e032-7c56-11eb-290b-23dc34edfc58 45 | md"# Functions and Differentiation" 46 | 47 | # ╔═╡ d88705f0-7c57-11eb-1950-bd54523e4a72 48 | md" This session draws heavily from a course on computational thinking that is presented at MIT, which can be found [here](https://computationalthinking.mit.edu/Spring21/). Much of what we present here has been taken directly from these notes. We will start with basics on functions, in order to make sure everyone is one the same page with respect to this fundamental concept. 49 | 50 | Once we have explored the idea of a function representation, we move to a really cool way in which you can take derivatives. This method is called `autodiff`, which is short for automatic differentiation. With this method we can automatically compute **exact** derivatives (up to floating-point error) given only the function itself. 51 | 52 | This method of taking derivatives is used widely in machine learning and optimisation and has become increasingly popular over the last couple of years. An excellent reference for all things optimisation, which also uses Julia as the main code base, can be found [here](https://algorithmsbook.com/optimization/#). The main message from this session will be to invest some time into understanding the implementation of autodiff, you don't really need to fully understand how it is constructed, just how to use it." 53 | 54 | # ╔═╡ 45aed8a2-7c59-11eb-3f69-e701041d6a30 55 | md" ## Functions (in Julia)" 56 | 57 | # ╔═╡ 7cfa32e4-7c58-11eb-32c0-5760739f6de4 58 | md""" 59 | Before we get started with automatic differentiation, let us just make sure that everyone is up to speed on the basics of functions. Remember that a function is defined as a relation which assigns to each element in the domain a **single element** in the range. A relation is a set of ordered pairs, $(x, y)$. The set of first coordinates is the domain, the set of second coordinates the range of the relation. Therefore a function is simply a mapping from values in the domain to a single value in the range. 60 | 61 | The first type of functions you learned about were **univariate** functions or real-valued functions functions of a single variable e.g. $f₁(x)=x^2$, $f₂(x)=\sin(x)$, $f₃(x)=x^\alpha$. 62 | 63 | In Julia, functions can be written in short form, anonymous form, or long form. 64 | """ 65 | 66 | # ╔═╡ a3d72150-87e9-11eb-29de-7d2adebbf9a7 67 | f₁(x) = x^2 # Short form 68 | 69 | # ╔═╡ cb0ac2ce-87e9-11eb-3c26-ed50a59978be 70 | x -> sin(x) # Anonymous form (lambda function) 71 | 72 | # ╔═╡ ce2c915c-8b3f-11eb-0c24-5727e31119b7 73 | md" We can give this anonymous function a name if we really wanted to." 74 | 75 | # ╔═╡ dabd966e-8b3f-11eb-3092-b16c6c39b80f 76 | f₂ = x -> sin(x) 77 | 78 | # ╔═╡ dfcad438-87e9-11eb-0fd2-218a4806a08c 79 | # Long form 80 | 81 | function f₃(x, α = 3) 82 | x^α # Julia automatically returns the last line in the code block 83 | end 84 | 85 | # ╔═╡ 59934d80-9063-11eb-0956-15e084f8135a 86 | md" Now that we have established how to think about functions, let us move on to how we can take derivatives of these functions." 87 | 88 | # ╔═╡ dbafac10-9062-11eb-169e-cf0cbd50df46 89 | md" ## Differentiation " 90 | 91 | # ╔═╡ ea99e100-9062-11eb-22d6-7d295c16f30a 92 | md" In this section we will cover different forms of differentiation. Traditionally one would do derivatives by hand and input that derivative into the computer. This is called manual differentiation. This method is slow and prone to human error. See the following example. " 93 | 94 | # ╔═╡ ad3c14d0-9063-11eb-153d-e3efee72a8d5 95 | g(x) = exp(2x) - x^3 96 | 97 | # ╔═╡ e21fa9a2-9063-11eb-389e-5f294f5762f0 98 | g_prime(x) = 2exp(2x) - 3x^2 99 | 100 | # ╔═╡ f618e202-9063-11eb-3f97-cb280350cbc9 101 | md" We can evaluate the function and its derivative at certain points, but once again we want something more automatic than this. " 102 | 103 | # ╔═╡ 2622db40-9064-11eb-156c-e9195c13dbd7 104 | md" #### Automatic differentiation " 105 | 106 | # ╔═╡ acf5a080-9064-11eb-0b61-55cf13f599c7 107 | md" In this section we will quickly mention how to implement automatic differentiation, but we will not go into detail about how it actually works. The video below gives a great overview of the process of automatic differentiation. [Here](https://julia.quantecon.org/more_julia/optimization_solver_packages.html) is a more advanced set of notes on the topic of differentiable programming and automatic differentiation in Julia. " 108 | 109 | # ╔═╡ 6a139650-9064-11eb-3f45-41506ea4e0f0 110 | html""" 111 | 112 | 113 | 114 | """ 115 | 116 | # ╔═╡ 6ad1feb0-87ea-11eb-14fb-2b73c5bacf7d 117 | md" In terms of the univariate functions we defined above it is easy to perform automatic differentiation. This method of differentiation is different from symbolic differentiaion that you will encounter in calculus or numerical differentition via first differences." 118 | 119 | # ╔═╡ b930ded2-87ea-11eb-3f26-3d4e1597615b 120 | md" Autodifferentiation is used in many machine learning and scientific computing applications, so it is a useful tool to know. In order to take calculate the derivative of our function $f₁(x)$ and it evaluate it at $x = 10$ we only have to do the following." 121 | 122 | # ╔═╡ 5e60acc0-8b38-11eb-11be-3bb33c2e8c72 123 | ForwardDiff.derivative(f₁, 10) # Derivative of x² evaluated at x = 10 124 | 125 | # ╔═╡ cb201760-8b38-11eb-266a-0572493239ae 126 | ForwardDiff.derivative( x -> f₃(x, 3), 10) # Derivative of x³ at x = 10 127 | 128 | # ╔═╡ 93607132-8b38-11eb-0359-2705eb558814 129 | md" As observed from the last equation, we could also use the anonymous function notation. In this case with the parameter set to $\alpha = 3$." 130 | 131 | # ╔═╡ 347785f0-906f-11eb-08e9-69ba5d3e4bf3 132 | md" One can repeat the same calculations with a reverse-mode automatic differentiation package called `Zygote.jl`. This is one of the newest and most exciting implementations of automatic differentiation in Julia and is used in the `Flux.jl` package, which is the foundational machine learning package in Julia. " 133 | 134 | # ╔═╡ 677fe790-906e-11eb-03b4-c1545d5f7e3c 135 | f₁'(10) # Using Zygote 136 | 137 | # ╔═╡ fcf37cb0-906e-11eb-37f3-5bbec323e815 138 | f₃'(10) 139 | 140 | # ╔═╡ c0cb6d4a-87ec-11eb-348b-e540882173e3 141 | md" There are several packages available to perform automatic differentiation in Julia. [Here](https://juliadiff.org/) is a curated list of all actively maintained `autodiff` packages. We were using `ForwardDiff.jl` and `Zygote.jl`. You can read more about how to use `Zygote` at the [website](https://fluxml.ai/Zygote.jl/latest/). " 142 | 143 | # ╔═╡ 95c81368-8b3a-11eb-27bd-59e48dbc509b 144 | md" #### Finite differences vs autodiff" 145 | 146 | # ╔═╡ e9c48a0c-8b38-11eb-373e-3fc1ea18d52b 147 | md" Consider the following example to see how much better the automatic differentiation representation of $f_4(x) = \sin(x)$ is compared to that of finite differences. 148 | 149 | Note: Remember from calculus that the derivative of $\sin(x)$ is $\cos(x)$. " 150 | 151 | # ╔═╡ bd76ca72-8b39-11eb-0147-252776c0eddf 152 | md" The finite difference method computes the difference between two values that differ by a finite step size. Finite differences utilises the limit definition of a derivative, namely 153 | 154 | $\frac{df_{4}(x)}{dx} \equiv \lim_{\epsilon \rightarrow 0}\frac{\sin(x+\epsilon) - \sin(x)}{\epsilon}$ 155 | 156 | However, we cannot use this definition directly, since we can let $t = 1/\epsilon$ and then reframe the problem such it has an infinite limit, which is shown below. 157 | 158 | $\frac{df_{4}(x)}{dx} \equiv \lim_{t \rightarrow \infty}\frac{\sin(x + 1/t) - \sin(x)}{1/t}$ 159 | 160 | We know from our previous session that the computer only has a finite space to store values for $t$, so to avoid overflow issues, we need to have a finite representation. A **forward difference** representation looks exactly like the formal definition but without the limit component. 161 | 162 | $\frac{df_{4}(x)}{dx} \approx \frac{\sin(x+\epsilon) - \sin(x)}{\epsilon}$ 163 | 164 | The slider below allows us to determine the value for magnitude of $\epsilon$. Smaller values of $\epsilon$ lead to higher precision approximation of the derivative through finite difference approximation. 165 | 166 | " 167 | 168 | # ╔═╡ 75f95eb2-8b39-11eb-211f-512a656e2f36 169 | begin 170 | md""" 171 | $(@bind e Slider(-17:-1, default=-1, show_value=true)) 172 | """ 173 | end 174 | 175 | # ╔═╡ 9e029a72-8b39-11eb-0a25-6dc0aa5e1d4e 176 | ϵ = 10.0^e 177 | 178 | # ╔═╡ 327cf250-8b4f-11eb-16b6-e709eb78504c 179 | md" The different approaches are finite differences, symbolic differentiation, automatic differentiation. These representations are evaluated at $x = 1$ below." 180 | 181 | # ╔═╡ a567131a-8b39-11eb-0769-11888a3de6b6 182 | (sin(1+ϵ)-sin(1))/ϵ , cos(1), ForwardDiff.derivative(sin,1), sin'(1) 183 | 184 | # ╔═╡ 4083acc0-9065-11eb-02d9-83b9411801ec 185 | md" We see that we get different answers for the different methods. The answer also seems to depend on the value that we choose for $\epsilon$. The reason for this has to do with truncation and rounding error, topics that we mentioned in the previous session. Normally there is a tradeoff between truncation and rounding error and one would like to pick a value for $\epsilon$ that provides the lowest level of truncation and rounding error. Picking the value for $\epsilon$ can be really hard, so we can use the `FiniteDifferences.jl` package in Julia to do it for us." 186 | 187 | # ╔═╡ 3d133d20-9070-11eb-0b1d-2533e8ab4355 188 | forward_fdm(12, 1)(sin, 1) # 5th order forward difference 189 | 190 | # ╔═╡ dfc3a550-9070-11eb-0ac2-21fcd1db7a0d 191 | md" Below is a quick discussion on truncation and rounding error. This gives us an idea of why are getting our particular errors. " 192 | 193 | # ╔═╡ 30f39ae0-9065-11eb-3acf-5766f18d038a 194 | md" ##### Truncation error " 195 | 196 | # ╔═╡ 9f50c068-8da8-11eb-2017-27fb9a5b87a4 197 | md" With 'large' values of $\epsilon$ our estimate seems to be quite far off from the actual answer. This is due to truncation error. We are trying to emulate the value for $\epsilon$ going to zero, but we are choosing a nonzero value to represent $\epsilon$. Consider the following example to understand the problem. " 198 | 199 | # ╔═╡ 8d7d0710-9065-11eb-3b33-2be258397e78 200 | h(x) = 5x^3 201 | 202 | # ╔═╡ afdfaba0-9065-11eb-2dd0-d9e5380faf3c 203 | h_prime(x) = 15x^2 204 | 205 | # ╔═╡ c1953590-9065-11eb-2e9a-3b9cd59eb1fe 206 | h(7) 207 | 208 | # ╔═╡ c55aa200-9065-11eb-2fe3-dfac936d1a72 209 | h_prime(7) 210 | 211 | # ╔═╡ cd5f65d0-9065-11eb-391d-c3083aba15e1 212 | h_prime_approx = (h(7 + 0.25) - h(7))/0.25 213 | 214 | # ╔═╡ f067c042-9065-11eb-0821-719c6a92b150 215 | TE = h_prime(7) - h_prime_approx 216 | 217 | # ╔═╡ 616e1e50-9067-11eb-3f55-4310dee68485 218 | md" The question is why do we get this truncation error. Well the answer can be depicted with the following calculation. This section is optional." 219 | 220 | # ╔═╡ 7c3c7420-9067-11eb-1aa3-236072753a44 221 | md" We can begin with a Taylor series expansion where we have 222 | 223 | $f(x + \epsilon) = f(x) + \epsilon \frac{d f(x)}{dx} + \frac{\epsilon^2}{2!} \frac{d^2 f(x)}{dx^2} + \frac{\epsilon^3}{3!} \frac{d^3 f(x)}{dx^3} + \cdots$ 224 | 225 | If we use the forward difference representation to approximate our derivative then the Taylor series expansion will give the following 226 | 227 | $\frac{f(x + \epsilon) - f(x)}{\epsilon} = \frac{d f(x)}{dx} + \left[\frac{\epsilon}{2!} \frac{d^2 f(x)}{dx^2} + \frac{\epsilon^2}{3!} \frac{d^3 f(x)}{dx^3} + \cdots \right]$ 228 | 229 | The term on the left hand side is the numerical approximation, then on the right hand side the first term is the true derivative. The component in brackets is the truncation error." 230 | 231 | # ╔═╡ 4cc1df10-9066-11eb-0938-e56149d21210 232 | md" ##### Rouding error " 233 | 234 | # ╔═╡ 22188120-9065-11eb-2c2a-e9eddcfab479 235 | md" We observe that with finite differences the answer is closer to the true value with smaller values of $\epsilon$. There is one thing that we must take into consideration here. Remember our old enemy, catastrophic cancellation! 236 | 237 | Since we are taking differences, we can often encounter issues when the values of $\epsilon$ are really small, since this means that $\sin(x+\epsilon)$ will be close to $\sin(x)$. We need to be careful that values don't cancel out in our calculation. In fact if you run the slider back far enough you will see the cancellation occur in our example. 238 | 239 | Let us illustrate this point in more detail with another example. Let us calculate the derivative of $x^2$ at $x = 2$ with finite differences. " 240 | 241 | # ╔═╡ 49de4d34-8da9-11eb-030b-59bb806f26cb 242 | ds(ϵ, x) = ((x + ϵ)^2 - x^2)/ϵ 243 | 244 | # ╔═╡ 78fddcce-8da9-11eb-1acd-eb95a14a2673 245 | HTML("The deriviative with ϵ = 1e-8 is: $(ds(1e-8, 2.))") 246 | 247 | # ╔═╡ b5691a34-8da9-11eb-09ae-af3a5f3746af 248 | HTML("The deriviative with ϵ = 1e-12 is: $(ds(1e-12, 2.))") 249 | 250 | # ╔═╡ b53499da-8da9-11eb-06b9-038a539e6b5a 251 | HTML("The deriviative with ϵ = 1e-16 is: $(ds(1e-16, 2.))") 252 | 253 | # ╔═╡ b5087744-8da9-11eb-027e-4d9008814177 254 | HTML("The deriviative with ϵ = 1e-1 is: $(ds(1e-1, 2.))") 255 | 256 | # ╔═╡ c932e536-8dae-11eb-1cc9-015e3ab7c8ea 257 | ((2 + ϵ)^2 - 2^2)/ϵ 258 | 259 | # ╔═╡ b4ed0598-8da9-11eb-3dc1-d39ba25b0aef 260 | md" So we see in this case that the derivative with $\epsilon = 10^{-16}$ actually results in subtractive cancellation and we get an answer that is completely wrong. We can solve these rounding issues by picking an optimal value for ϵ. This optimal value can be shown to be $ϵ = \max\{|x|, 1\}\sqrt{\text{eps}}$ where $\text{eps}$ refers to machine epsilon. " 261 | 262 | # ╔═╡ a65b9ec6-8daa-11eb-3529-1de77b221d3e 263 | md" #### Errors and finite differences (optional) " 264 | 265 | # ╔═╡ c3a2963a-8daa-11eb-38e5-8198e6c46ac3 266 | md" We have to ask ourselves whether there is a way to measure the error growth rate in ϵ. In order to do this we have to perform a first order Taylor expansion of our function of interest around the value where the function is to be evaluated. In other words, Taylor expansion of $f(x)$ around $x$. 267 | 268 | $f(x + ϵ) = f(x) + f'(x)ϵ + \mathcal{O}(ϵ^{2})$ 269 | 270 | The $\mathcal{O}(ϵ^{2})$ means that our error in the approximation grows at quadratically in ϵ, which seems strange since we took a linear approximation. 271 | " 272 | 273 | # ╔═╡ c3867f52-8daa-11eb-1c17-1f51a914b7a1 274 | md" To better understand this error approximation, let us rearrange the Taylor expansion. 275 | 276 | $f'(x) = \frac{f(x + ϵ) - f(x)}{ϵ} + \mathcal{O}(ϵ^2)/ϵ$ 277 | 278 | This better reflects the fact that forward differences has *linearly* growing errors, since $\mathcal{O}(ϵ^2)/ϵ = \mathcal{O}(ϵ)$. This means that if we halve $ϵ$ we will also halve the error in our approximation. This ignores issues surrounding rounding though. 279 | 280 | " 281 | 282 | # ╔═╡ 4ec7be62-8dad-11eb-2099-2d76bc183810 283 | md" There are ways to improve on the accuracy of the finite difference method. One could, as an example, use central differences instead of finite differences. The central difference representation for our equation from before is: 284 | 285 | $\frac{df_{4}(x)}{dx} \approx \frac{\sin(x+\epsilon) - \sin(x - \epsilon)}{2\epsilon}$ 286 | 287 | The error will grow much slower with this representation, as opposed to forward differences, so it seems to be more beneficial to use this. However, one needs to consider that for with central differences there are many more computations to perform, since we need to evaluate the function twice in each iteration. This means that forward differences are computationally more efficient, but less accurate. " 288 | 289 | # ╔═╡ 3fb7e3e6-8b4d-11eb-308d-f1d31d42e184 290 | md" #### What about symbolic differentiation? " 291 | 292 | # ╔═╡ 1a011e5c-8b4c-11eb-1996-ed9145ec9ee7 293 | md" An alternative to automatic differentiation and finite differences would be to use the _SymEngine.jl_ package to do symbolic differentiation. One could also use the _SymPy_ package from Python directly in Julia. For symbolic differentiation and manipulation _Mathematica_ is probably the most sophisticated, so if you have to do symbolic work, you should work in that space. " 294 | 295 | # ╔═╡ 57a46a0a-8b4c-11eb-1210-cf6a303f32ac 296 | @vars s; 297 | 298 | # ╔═╡ 5da00e52-8b4c-11eb-199c-c1b0fda27cc3 299 | f₄ = sin(s) 300 | 301 | # ╔═╡ 75ed19fa-8b4c-11eb-0873-4b96f4617096 302 | diff(f₄, s) 303 | 304 | # ╔═╡ 97c0c0a4-8b4c-11eb-218d-6fb509350f95 305 | md" This seems to give us the answer that we were looking for. The derivative of $\sin(x)$ is $\cos(x)$." 306 | 307 | # ╔═╡ 3e4817d0-9069-11eb-0e44-5f73ff9bfc73 308 | md" Symbolic differentiation works quite well, but there is the problem of *expression swell*. In this case we have that derivative expressions are many times larger than the original function. You can read on the topic [here](http://www-troja.fjfi.cvut.cz/~liska/ca/node53.html). This idea is also nicely described in the video posted above. " 309 | 310 | # ╔═╡ f603ce46-8b41-11eb-0d87-99b9c580169e 311 | md" Next we move into the world of scalar valued multivariate functions. A scalar valued function takes one or more inputs and only retuns a single value. So this means that our function in this setting will take in multiple variables with potentially different values attached to those variables and only return a single value. A general case would be an $n$-variable scalar valued function that maps from the space $\mathbb{R}^{n}$ to $\mathbb{R}$." 312 | 313 | # ╔═╡ cf684c20-8b42-11eb-36e0-c318082f9f4f 314 | md" ### Scalar valued multivariate functions " 315 | 316 | # ╔═╡ e1cca2ee-8b42-11eb-0471-23a6523e7779 317 | md" Let us consider an example of a scalar valued multivariate function $f_5(x): \mathbb{R}^{3} \rightarrow \mathbb{R}$, 318 | 319 | $f_5(\textbf{x}) = 5\sin(x_1 * x_2) + 2x_2 / 4x_3$" 320 | 321 | # ╔═╡ 189c3176-8b44-11eb-03fe-71a833f4d5e6 322 | md" There are multiple ways in Julia in which we can write this type of function. One can represent it as a function of many variables or a function of a vector. " 323 | 324 | # ╔═╡ c68350a4-8b43-11eb-0113-8ff369685239 325 | # Different ways to represent scalar valued multivariate function 326 | 327 | begin 328 | f₅(x, y, z) = 5sin(x*y) + 2y/4z 329 | f₅(v) = 5*sin(v[1]*v[2]) + 2*v[2]/4v[3] 330 | end 331 | 332 | # ╔═╡ 8711b310-8b44-11eb-3311-0b51038cab72 333 | md" Once the code cell has been executed, you will see that a `generic function with 2 methods` has been created. In this case, depending on whether you use a vector or list with three elements, you will call a different version of $f_5$. Let us illustrate with an example. " 334 | 335 | # ╔═╡ a3188eb2-8b44-11eb-3043-6faea3ffd81f 336 | f₅(1,2,3) # Input is a list of three elements (x, y, z) 337 | 338 | # ╔═╡ abde4208-8b44-11eb-1e72-29ca3336a118 339 | f₅([1,2,3]) # Input is a vector v (with three elements) 340 | 341 | # ╔═╡ ca5cf856-8d70-11eb-1d37-135bdd1a95c7 342 | md" The fact that the same function name can do different things depending on the type of input is referred to as **multiple dispatch**. Most functions have this feature in Julia." 343 | 344 | # ╔═╡ 0903d2fe-8b45-11eb-2700-292eac0f88f7 345 | md" There is an even more efficient way of coding the portion above. Remember that programmers are lazy and don't want to copy code. You want to reuse code as much as possible. Look at the following code block and see if you can figure out how this abstraction works. I think it is quite elegant. " 346 | 347 | # ╔═╡ ca4cf144-8b44-11eb-11a7-9f5b1511f14f 348 | begin 349 | f₆(x, y, z) = 5sin(x*y) + 2y/4z 350 | f₆(v) = f₆(v[1], v[2], v[3]) # Does this part make sense to you? Think about what this is actually doing. 351 | end 352 | 353 | # ╔═╡ 6685b140-8b45-11eb-08b8-6dc1fefab50b 354 | f₆(1,2,3), f₆([1,2,3]) 355 | 356 | # ╔═╡ a83a91e8-8b4d-11eb-02f1-0506c0723d00 357 | md" The gradient is a generalisation of the concept of derivative to multivariate functions. It provides the local slope of the function, which gives some idea of what is going to happen if take a small step in a certain direction on that function. In the single vairable setting derivatives are slopes of tangent lines, while in the multivariate case we know that the gradients point in the direction of steepest ascent of the tangent **hyperplane**. " 358 | 359 | # ╔═╡ 7ec6d044-7c58-11eb-112d-5d8be6b4288c 360 | md" #### Nabla! $\nabla$! " 361 | 362 | # ╔═╡ 7ee10e48-7c58-11eb-2e3b-f5805d4af19c 363 | md" In scientific computing and especially in machine learning one needs to take derivatives of multivariate functions in the direction of every argument. Collecting the partial derivatives in a vector provides us with the gradient. The gradient of the function $f$ evaluated at $\textbf{x}$ is normally written as $\nabla f(\textbf{x})$, where: 364 | 365 | $\nabla f(\textbf{x}) = \left[\frac{\partial f(\textbf{x})}{\partial x_1}, \frac{\partial f(\textbf{x})}{\partial x_2}, \frac{\partial f(\textbf{x})}{\partial x_3}\right]$" 366 | 367 | # ╔═╡ 7f14d2fa-7c58-11eb-1e88-773a06148b22 368 | md" You can calculate this gradient explicitly in the manner specified below. This becomes a bit more difficult to do when the number of dimensions increase, but it is good to see in order to establish intuition for what we are doing. " 369 | 370 | # ╔═╡ 7f2f1b06-7c58-11eb-038e-15bd2b4d1dbb 371 | begin 372 | ∂f₅∂x = (f₅(1+ϵ, 2, 3 ) -f₅(1, 2, 3)) / ϵ 373 | ∂f₅∂y = (f₅(1, 2+ϵ, 3 ) -f₅(1, 2, 3)) / ϵ 374 | ∂f₅∂z = (f₅(1, 2, 3+ϵ) -f₅(1, 2, 3)) / ϵ 375 | ∇f = [ ∂f₅∂x , ∂f₅∂y, ∂f₅∂z] 376 | end 377 | 378 | # ╔═╡ ef8bc500-8ce0-11eb-380f-618627e4d182 379 | md" Since the method above requires many evaluations to compute, it is considered to be inefficient. A better alternative is to simply use automatic differentiation to find the gradient. In fact, most machine learning algorithms that are looking for specific loss functions are using automatic differentiation procedures." 380 | 381 | # ╔═╡ 7efab6f4-7c58-11eb-006e-412089f351a0 382 | ForwardDiff.gradient(f₅, [1, 2, 3]) 383 | 384 | # ╔═╡ d1606590-906e-11eb-1846-1500a526a8a8 385 | gradient(f₅, [1, 2, 3]) # Using Zygote 386 | 387 | # ╔═╡ f86ef080-8cdf-11eb-3540-59c2bd06a1e5 388 | md" #### Surface plots in Julia " 389 | 390 | # ╔═╡ d3d5e292-8cdf-11eb-1a17-8d5ceebaaf91 391 | md" Let us draw some figures here to illustrate the function in three dimensions. We can look at the function $f_{7}(\textbf{x}) = \sin(x_1) + \cos(x_2)$. This is a relatively easy function to work with. and has a nice three dimensional representation. This part is mostly for fun, to get used to the idea of graphing in Julia. We are using the GR backend in this case, but you can use whatever plotting backend that you prefer. The plotting in Julia is quite similar to Matlab and shares some similarity with Python's `matplotlib` package. " 392 | 393 | # ╔═╡ 7f9507f4-7c58-11eb-045d-ad36f4fb184a 394 | x₁ = 8 .* rand(100) .- 4; 395 | 396 | # ╔═╡ 7faea394-7c58-11eb-2529-c3881c14b364 397 | x₂ = 8 .* rand(100) .- 4; 398 | 399 | # ╔═╡ 50ad955c-8ce1-11eb-1e93-d7a3cc6a89fe 400 | f₇ = sin.(x₁) + cos.(x₂); 401 | 402 | # ╔═╡ e1f0ef0a-8ce1-11eb-022b-adfd5162cdc2 403 | md" Now let us plot our surface plot of the function we defined. I think it looks pretty cool! " 404 | 405 | # ╔═╡ 88be634a-8ce1-11eb-0aa3-3f3783bc5eba 406 | wireframe(x₁, x₂, f₇) 407 | 408 | # ╔═╡ 6df8832c-8ce6-11eb-09bf-b15a882acc1a 409 | md" You might have noticed in the construction of the graph that there is this `.` following the $\sin$ and $\cos$ function. You can also see this operator in previous lines of code in front of `*` and `-`. If you enact this operator you are `broadcasting` the operation across all the elements of the array." 410 | 411 | # ╔═╡ 4774616c-8db0-11eb-2368-cd1cc4cc884e 412 | md" ### Broadcasting " 413 | 414 | # ╔═╡ 5891437a-8db0-11eb-0157-8d8f9b77e1fb 415 | md" If we take a closer look at the first line of code in the plotting section we see that we are taking the value of 8 and multiplying it with `rand(100)`. First, you need to ask yourself, what is `rand(100)` doing. Let's type it in to see. You should also consult the documentation on this command to get a better idea of what is happening when you call this function. " 416 | 417 | # ╔═╡ bbff790e-8db0-11eb-1c0b-4b8eff5e4b5e 418 | rand(100) 419 | 420 | # ╔═╡ e313133e-8db0-11eb-01eb-cd399ba999cb 421 | typeof(rand(100)) 422 | 423 | # ╔═╡ bf8478fe-8db0-11eb-2576-45a741c4377d 424 | md" It appears that it creates an array, in this case a **column vector**, that contains $100$ floating-point values. It chooses these values randomly from a uniform distribution in the interval $[0, 1)$." 425 | 426 | # ╔═╡ bf9b99c6-8db0-11eb-0c14-195455bf6f0b 427 | md" If we wanted to multiply each of the values in this vector by 8 then it seems that we could simply do scalar multiplication. In this case the scalar multiplication will work without using the `.` operator. So we can proceed with or without it. " 428 | 429 | # ╔═╡ bfe58446-8db0-11eb-0e8d-51939d21730d 430 | 8 * rand(100) 431 | 432 | # ╔═╡ b3f1ab8c-8db1-11eb-3cba-1792c29af5d0 433 | 8 .* rand(100) 434 | 435 | # ╔═╡ bfff84e0-8db0-11eb-1a00-dfe087e10c2e 436 | md" Both of these methods will work with multiplication. However, when we apply subtraction we get an error. It says that if we want element-wise subtraction we need to use broadcasting with dot syntax." 437 | 438 | # ╔═╡ c01b2a2e-8db0-11eb-3422-0b59816077fe 439 | 8 .* rand(100) - 4 440 | 441 | # ╔═╡ ca24f6de-8db1-11eb-19bc-f71b8b226c39 442 | md" This then indicates to us that the broadcasting operation allows us to subtract 4 from each of the components in the vector in an elementwise fashion. " 443 | 444 | # ╔═╡ c03422fe-8db0-11eb-34d3-4bf88e1da37e 445 | 8 .* rand(100) .- 4 446 | 447 | # ╔═╡ 2700f722-8db2-11eb-3993-4f7392659ef8 448 | md" In most instances you can use the broadcast operator across all functions without worrying with it too much. Julia is quite good at figuring out when you should be broadcasting. " 449 | 450 | # ╔═╡ Cell order: 451 | # ╟─1c7f7f74-7c57-11eb-293a-d1be483a7ca0 452 | # ╟─7819e032-7c56-11eb-290b-23dc34edfc58 453 | # ╟─d88705f0-7c57-11eb-1950-bd54523e4a72 454 | # ╟─45aed8a2-7c59-11eb-3f69-e701041d6a30 455 | # ╟─7cfa32e4-7c58-11eb-32c0-5760739f6de4 456 | # ╠═a3d72150-87e9-11eb-29de-7d2adebbf9a7 457 | # ╠═cb0ac2ce-87e9-11eb-3c26-ed50a59978be 458 | # ╟─ce2c915c-8b3f-11eb-0c24-5727e31119b7 459 | # ╠═dabd966e-8b3f-11eb-3092-b16c6c39b80f 460 | # ╠═dfcad438-87e9-11eb-0fd2-218a4806a08c 461 | # ╟─59934d80-9063-11eb-0956-15e084f8135a 462 | # ╟─dbafac10-9062-11eb-169e-cf0cbd50df46 463 | # ╟─ea99e100-9062-11eb-22d6-7d295c16f30a 464 | # ╠═ad3c14d0-9063-11eb-153d-e3efee72a8d5 465 | # ╠═e21fa9a2-9063-11eb-389e-5f294f5762f0 466 | # ╟─f618e202-9063-11eb-3f97-cb280350cbc9 467 | # ╟─2622db40-9064-11eb-156c-e9195c13dbd7 468 | # ╟─acf5a080-9064-11eb-0b61-55cf13f599c7 469 | # ╠═6a139650-9064-11eb-3f45-41506ea4e0f0 470 | # ╟─6ad1feb0-87ea-11eb-14fb-2b73c5bacf7d 471 | # ╟─b930ded2-87ea-11eb-3f26-3d4e1597615b 472 | # ╠═5e60acc0-8b38-11eb-11be-3bb33c2e8c72 473 | # ╠═cb201760-8b38-11eb-266a-0572493239ae 474 | # ╟─93607132-8b38-11eb-0359-2705eb558814 475 | # ╟─347785f0-906f-11eb-08e9-69ba5d3e4bf3 476 | # ╠═677fe790-906e-11eb-03b4-c1545d5f7e3c 477 | # ╠═fcf37cb0-906e-11eb-37f3-5bbec323e815 478 | # ╟─c0cb6d4a-87ec-11eb-348b-e540882173e3 479 | # ╟─95c81368-8b3a-11eb-27bd-59e48dbc509b 480 | # ╟─e9c48a0c-8b38-11eb-373e-3fc1ea18d52b 481 | # ╟─bd76ca72-8b39-11eb-0147-252776c0eddf 482 | # ╟─75f95eb2-8b39-11eb-211f-512a656e2f36 483 | # ╠═9e029a72-8b39-11eb-0a25-6dc0aa5e1d4e 484 | # ╟─327cf250-8b4f-11eb-16b6-e709eb78504c 485 | # ╠═a567131a-8b39-11eb-0769-11888a3de6b6 486 | # ╟─4083acc0-9065-11eb-02d9-83b9411801ec 487 | # ╠═3d133d20-9070-11eb-0b1d-2533e8ab4355 488 | # ╟─dfc3a550-9070-11eb-0ac2-21fcd1db7a0d 489 | # ╟─30f39ae0-9065-11eb-3acf-5766f18d038a 490 | # ╟─9f50c068-8da8-11eb-2017-27fb9a5b87a4 491 | # ╠═8d7d0710-9065-11eb-3b33-2be258397e78 492 | # ╠═afdfaba0-9065-11eb-2dd0-d9e5380faf3c 493 | # ╠═c1953590-9065-11eb-2e9a-3b9cd59eb1fe 494 | # ╠═c55aa200-9065-11eb-2fe3-dfac936d1a72 495 | # ╠═cd5f65d0-9065-11eb-391d-c3083aba15e1 496 | # ╠═f067c042-9065-11eb-0821-719c6a92b150 497 | # ╟─616e1e50-9067-11eb-3f55-4310dee68485 498 | # ╟─7c3c7420-9067-11eb-1aa3-236072753a44 499 | # ╟─4cc1df10-9066-11eb-0938-e56149d21210 500 | # ╟─22188120-9065-11eb-2c2a-e9eddcfab479 501 | # ╠═49de4d34-8da9-11eb-030b-59bb806f26cb 502 | # ╟─78fddcce-8da9-11eb-1acd-eb95a14a2673 503 | # ╟─b5691a34-8da9-11eb-09ae-af3a5f3746af 504 | # ╟─b53499da-8da9-11eb-06b9-038a539e6b5a 505 | # ╟─b5087744-8da9-11eb-027e-4d9008814177 506 | # ╠═c932e536-8dae-11eb-1cc9-015e3ab7c8ea 507 | # ╟─b4ed0598-8da9-11eb-3dc1-d39ba25b0aef 508 | # ╟─a65b9ec6-8daa-11eb-3529-1de77b221d3e 509 | # ╟─c3a2963a-8daa-11eb-38e5-8198e6c46ac3 510 | # ╟─c3867f52-8daa-11eb-1c17-1f51a914b7a1 511 | # ╟─4ec7be62-8dad-11eb-2099-2d76bc183810 512 | # ╟─3fb7e3e6-8b4d-11eb-308d-f1d31d42e184 513 | # ╟─1a011e5c-8b4c-11eb-1996-ed9145ec9ee7 514 | # ╠═57a46a0a-8b4c-11eb-1210-cf6a303f32ac 515 | # ╠═5da00e52-8b4c-11eb-199c-c1b0fda27cc3 516 | # ╠═75ed19fa-8b4c-11eb-0873-4b96f4617096 517 | # ╟─97c0c0a4-8b4c-11eb-218d-6fb509350f95 518 | # ╟─3e4817d0-9069-11eb-0e44-5f73ff9bfc73 519 | # ╟─f603ce46-8b41-11eb-0d87-99b9c580169e 520 | # ╟─cf684c20-8b42-11eb-36e0-c318082f9f4f 521 | # ╟─e1cca2ee-8b42-11eb-0471-23a6523e7779 522 | # ╟─189c3176-8b44-11eb-03fe-71a833f4d5e6 523 | # ╠═c68350a4-8b43-11eb-0113-8ff369685239 524 | # ╟─8711b310-8b44-11eb-3311-0b51038cab72 525 | # ╠═a3188eb2-8b44-11eb-3043-6faea3ffd81f 526 | # ╠═abde4208-8b44-11eb-1e72-29ca3336a118 527 | # ╟─ca5cf856-8d70-11eb-1d37-135bdd1a95c7 528 | # ╟─0903d2fe-8b45-11eb-2700-292eac0f88f7 529 | # ╠═ca4cf144-8b44-11eb-11a7-9f5b1511f14f 530 | # ╠═6685b140-8b45-11eb-08b8-6dc1fefab50b 531 | # ╟─a83a91e8-8b4d-11eb-02f1-0506c0723d00 532 | # ╟─7ec6d044-7c58-11eb-112d-5d8be6b4288c 533 | # ╟─7ee10e48-7c58-11eb-2e3b-f5805d4af19c 534 | # ╟─7f14d2fa-7c58-11eb-1e88-773a06148b22 535 | # ╠═7f2f1b06-7c58-11eb-038e-15bd2b4d1dbb 536 | # ╟─ef8bc500-8ce0-11eb-380f-618627e4d182 537 | # ╠═7efab6f4-7c58-11eb-006e-412089f351a0 538 | # ╠═d1606590-906e-11eb-1846-1500a526a8a8 539 | # ╟─f86ef080-8cdf-11eb-3540-59c2bd06a1e5 540 | # ╟─d3d5e292-8cdf-11eb-1a17-8d5ceebaaf91 541 | # ╠═7f9507f4-7c58-11eb-045d-ad36f4fb184a 542 | # ╠═7faea394-7c58-11eb-2529-c3881c14b364 543 | # ╠═50ad955c-8ce1-11eb-1e93-d7a3cc6a89fe 544 | # ╟─e1f0ef0a-8ce1-11eb-022b-adfd5162cdc2 545 | # ╠═88be634a-8ce1-11eb-0aa3-3f3783bc5eba 546 | # ╟─6df8832c-8ce6-11eb-09bf-b15a882acc1a 547 | # ╟─4774616c-8db0-11eb-2368-cd1cc4cc884e 548 | # ╟─5891437a-8db0-11eb-0157-8d8f9b77e1fb 549 | # ╠═bbff790e-8db0-11eb-1c0b-4b8eff5e4b5e 550 | # ╠═e313133e-8db0-11eb-01eb-cd399ba999cb 551 | # ╟─bf8478fe-8db0-11eb-2576-45a741c4377d 552 | # ╟─bf9b99c6-8db0-11eb-0c14-195455bf6f0b 553 | # ╠═bfe58446-8db0-11eb-0e8d-51939d21730d 554 | # ╠═b3f1ab8c-8db1-11eb-3cba-1792c29af5d0 555 | # ╟─bfff84e0-8db0-11eb-1a00-dfe087e10c2e 556 | # ╠═c01b2a2e-8db0-11eb-3422-0b59816077fe 557 | # ╟─ca24f6de-8db1-11eb-19bc-f71b8b226c39 558 | # ╠═c03422fe-8db0-11eb-34d3-4bf88e1da37e 559 | # ╟─2700f722-8db2-11eb-3993-4f7392659ef8 560 | -------------------------------------------------------------------------------- /notebooks/topic-3.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.19.5 3 | 4 | using Markdown 5 | using InteractiveUtils 6 | 7 | # ╔═╡ 796b0922-8c17-11eb-31e8-59d5b21ee32b 8 | begin 9 | import Pkg 10 | Pkg.activate(mktempdir()) 11 | Pkg.add([ 12 | Pkg.PackageSpec(name="Images"), 13 | Pkg.PackageSpec(name="ImageMagick"), 14 | Pkg.PackageSpec(name="PlutoUI"), 15 | Pkg.PackageSpec(name="HypertextLiteral"), 16 | Pkg.PackageSpec(name="Random"), 17 | Pkg.PackageSpec(name="BenchmarkTools"), 18 | Pkg.PackageSpec(name="Plots"), 19 | Pkg.PackageSpec(name="Distributions") 20 | ]) 21 | using Random 22 | using BenchmarkTools 23 | using Images 24 | using PlutoUI 25 | using HypertextLiteral 26 | using LinearAlgebra 27 | using Plots 28 | using Distributions 29 | end 30 | 31 | # ╔═╡ 97dca378-8c17-11eb-1a9f-49d299180a72 32 | md" # Systems of linear equations" 33 | 34 | # ╔═╡ 8dd16592-8d9c-11eb-1adb-af30ea9f5bc5 35 | md" In this section we will cover some foundational concepts in (numerical) linear algebra. Our first section focuses on arrays in Julia. Following that we will move on to solving systems of linear equations. " 36 | 37 | # ╔═╡ d3a32206-96ff-11eb-0c21-953e0d446b50 38 | md""" 39 | !!! info 40 | For those of you who need a refresher on linear algebra, you can look [here](https://fncbook.github.io/fnc/appendix/linear-algebra.html) or [here](https://julia.quantecon.org/tools_and_techniques/linear_algebra.html). There is also a free book on applied linear algebra that has accompanying Julia code, which you can find [here](http://vmls-book.stanford.edu/). 41 | """ 42 | 43 | # ╔═╡ cdcc50b0-8c18-11eb-3188-ffb91dcecee8 44 | md" ## Arrays in Julia " 45 | 46 | # ╔═╡ dc8e8004-8d95-11eb-30c0-33a66a0c3f6b 47 | md" In this section I will be following similar material to that of the [Quantecon](https://julia.quantecon.org/getting_started_julia/fundamental_types.html) website. In some places the descriptions will be close to (or identical) to their depiction. The purpose of this notebook is to condense all the information into one place. These notes are no substitute for complete coverage on the topic, just a basic introduction. 48 | 49 | The first thing we need to consider in this section is our definition for an array. A technical definition is that an array is a rectangular grid that is used for storing data of any type. However, all of the data in the container should be of the same type! 50 | 51 | The basic array is constructed in a similar way to the that of Matlab, which can be done as follows: " 52 | 53 | # ╔═╡ eea539ae-8d95-11eb-1a13-d704f50969c3 54 | x₁ = [1.0, 2.0, 3.0] 55 | 56 | # ╔═╡ 1eeb8d5c-8d96-11eb-0bc1-0162c420760f 57 | typeof(x₁) 58 | 59 | # ╔═╡ e9140e2a-8d97-11eb-3a2c-79fad99882ea 60 | md" You might have encountered arrays in mathematics. An array can be one-dimensional, two-dimensional, three-dimensional and so forth. We can see that our example for `x` is a three element array that contains `Float64` values. The `1` means that this is a one-dimensional array, which is also known as a vector. In Julia it is best to think about these as **column vectors**. " 61 | 62 | # ╔═╡ 784d31a8-8d9a-11eb-02bc-a3a24bcb564c 63 | typeof(x₁) == Vector{Float64} 64 | 65 | # ╔═╡ 3329945f-d07f-4aa8-8715-b9cdebb5fd22 66 | md" One can also think of vectors in a graphical sense. In the following graph we see three different vectors in the three dimensional plane. " 67 | 68 | # ╔═╡ 61132429-1e0a-491a-b1e8-66dc45e72110 69 | begin 70 | x_vals = [0 0 0 ; 2 -3 -4] 71 | y_vals = [0 0 0 ; 4 3 -3.5] 72 | 73 | plot(x_vals, y_vals, arrow = true, color = :blue, 74 | legend = :none, xlims = (-5, 5), ylims = (-5, 5), 75 | annotations = [(2.2, 4.4, "[2, 4]"), 76 | (-3.3, 3.3, "[-3, 3]"), 77 | (-4.4, -3.85, "[-4, -3.5]")], 78 | xticks = -5:1:5, yticks = -5:1:5, 79 | framestyle = :origin) 80 | end 81 | 82 | # ╔═╡ ce128ae2-8d9b-11eb-0399-cda8550d4524 83 | md" You will notice if we attempt to create a row vector then it is considered two-dimensional. This means that row vectors are treated as matrices in a sense. This is mainly done for the purposes of multiplication and addition so that dimensions align in the right manner. Multiplying with a column vector is inherently different from multiplying with a row vector. It is good to take note of these subtleties. " 84 | 85 | # ╔═╡ 98dbd9c8-8d9b-11eb-009d-b93e1b869285 86 | x₂ = [1.0 2.0 3.0] 87 | 88 | # ╔═╡ ff747db4-8d9b-11eb-3a10-3314a843e679 89 | typeof(x₂) == Matrix{Float64} 90 | 91 | # ╔═╡ b386f1dc-8d9a-11eb-2bb8-a58a56b5a85b 92 | md" We have established that one-dimensional arrays are a vector type. Similarily, we can view a two-dimensional array as a matrix. Consider the following example." 93 | 94 | # ╔═╡ cb7dce80-8d9a-11eb-1f83-fb79238361e1 95 | x₃ = [1 2 3; 4 5 6; 7 8 14] 96 | 97 | # ╔═╡ 54db62f4-8d9b-11eb-34d6-9f4d16b251de 98 | typeof(x₃) == Matrix{Int64} 99 | 100 | # ╔═╡ 1b9b6594-8d9d-11eb-375a-79652da9dee1 101 | ndims(x₃) # Number of dimensions of x₃ 102 | 103 | # ╔═╡ 2ba16772-8d9d-11eb-0a26-c556fb0240aa 104 | size(x₃) # Tuple containing the dimensions of x₃ 105 | 106 | # ╔═╡ 2f5d84f6-9700-11eb-3dca-799c96c6b609 107 | typeof(size(x₃)) # Immutable type!! 108 | 109 | # ╔═╡ 438e6cba-9700-11eb-2c73-339e72e703cb 110 | md" It is important to note here that the *tuple* type is immutable. This means that you cannot change the values once you have created the tuple. Observe the error that we get if we want to alter a specific element of a tuple." 111 | 112 | # ╔═╡ 8f86a65a-9700-11eb-1633-95b7ef7e7295 113 | size(x₃)[1] = 2 # In this case we want to change the first element of the tuple 114 | 115 | # ╔═╡ a1cd647e-92f1-11eb-0ddb-fdc6a622bb8e 116 | size(x₃, 1) # Number of rows 117 | 118 | # ╔═╡ af513998-92f1-11eb-16c2-3bd34fe8a231 119 | size(x₃, 2) # Number of columns 120 | 121 | # ╔═╡ 859cee86-8d9d-11eb-2993-bb3f3d748df6 122 | length(x₃) # Number of elements in x₃ 123 | 124 | # ╔═╡ dfa715e2-8d9c-11eb-29e3-7dad0fad127f 125 | md" We see that our $3 \times 3$ matrix is a two-dimensional array. Take note of the difference between dimension and size of the matrix." 126 | 127 | # ╔═╡ cd94ab08-8d9c-11eb-2a76-673456a371ef 128 | md" ### Construction of arrays" 129 | 130 | # ╔═╡ 9bd1329e-8d9c-11eb-1751-fd348630580e 131 | md" There are many important ways to create and initialise arrays automatically in Julia. Some of the most important methods are shown below. See if you can figure out from the output what the functions are doing. " 132 | 133 | # ╔═╡ ae7906d8-8d9c-11eb-3e39-4fcddb18b1d2 134 | zeros(3) 135 | 136 | # ╔═╡ b28764ae-8d9c-11eb-10f7-8f4b2387665f 137 | zeros(3, 3) 138 | 139 | # ╔═╡ b7a8d21a-8d9c-11eb-106d-2f68dc163529 140 | fill(5.0, 3, 3) 141 | 142 | # ╔═╡ f29ef44a-8d9d-11eb-0dbe-d5cc7c1080db 143 | ones(3, 3) 144 | 145 | # ╔═╡ e358ae06-becb-4d26-ab5a-2e3eee274e54 146 | x₃ 147 | 148 | # ╔═╡ fb532bfe-8d9d-11eb-2a10-89d840f835df 149 | reshape(x₃, 1, 9) 150 | 151 | # ╔═╡ 16efc20a-8d9e-11eb-1819-47dd80edfc9b 152 | similar(x₃) # Fills with garbage from memory 153 | 154 | # ╔═╡ 08ef44e4-8da0-11eb-3d23-052a692e711f 155 | rand(Int64, 3, 3) 156 | 157 | # ╔═╡ 40b31e3c-8d9e-11eb-0c87-5bf71827d188 158 | rand(x₃, 3, 3) # This one is actually a bit tricky, you need to think about this. 159 | 160 | # ╔═╡ 58232b72-8d9e-11eb-0489-cfccbceb1e11 161 | randn(Float64, 3, 3) 162 | 163 | # ╔═╡ dab8d7f8-8d9e-11eb-0805-c7343db6c32b 164 | Matrix{Float64}(I, 3, 3) 165 | 166 | # ╔═╡ 3c9c9d0a-a13c-4e33-82b3-1d5cfec04c3f 167 | typeof(I) 168 | 169 | # ╔═╡ 72390509-65be-4508-802e-458869d49b23 170 | x₃ - I 171 | 172 | # ╔═╡ e5bee5de-8d9e-11eb-12af-617d270d651a 173 | range(0, 100, length = 51) # Similar to `linspace` in Matlab 174 | 175 | # ╔═╡ e6c21a46-9311-11eb-3655-0dce4406e2c5 176 | md" The next step is to think about indexing of our constructed matrices / arrays. In other words, how do we get specific values out of our created arrays. " 177 | 178 | # ╔═╡ f03aece2-9311-11eb-1467-c73576cd3184 179 | md" ### Indexing " 180 | 181 | # ╔═╡ 1398128c-9312-11eb-3f28-07be67646964 182 | md" The indexing will be very familiar to those that use Matlab and R, not so much for Python. Let us work with x₃ here. Recall that that is the following matrix. " 183 | 184 | # ╔═╡ ff94ad36-9311-11eb-297d-5192bd1882ec 185 | x₃ 186 | 187 | # ╔═╡ 113271b0-9312-11eb-13c2-cd42aaf2ba53 188 | x₃[:, 1] # Provides us with the first column (all the rows of the first column) 189 | 190 | # ╔═╡ 60e1fce2-9312-11eb-19db-df30cb82005f 191 | x₃[1, :] # Provides the first row (all the columns of the first row) 192 | 193 | # ╔═╡ 44e3c3c2-9312-11eb-34a4-e3a6b4e5d937 194 | x₃[1:2, 2:3] # Creates a sub-array. Can you figure out how this works? 195 | 196 | # ╔═╡ f2d1cce0-9312-11eb-0747-3f0c6f75c1c2 197 | md" **Important!** Creating subsets of an array creates a copy in Julia! It does not alter the original array. See what happens in the following example: " 198 | 199 | # ╔═╡ 35d91f66-9313-11eb-075c-3ba0a8b38f60 200 | z₃ = x₃[1:2, 2:3] 201 | 202 | # ╔═╡ 47bd69a6-9313-11eb-0aff-0116148e2a69 203 | z₃[2, 2] = 1.0 204 | 205 | # ╔═╡ 551fc65e-9313-11eb-3043-516e2886485f 206 | z₃ 207 | 208 | # ╔═╡ 59639cac-9313-11eb-008e-9fd2113271e7 209 | x₃ # x₃ did not change as a result of the change in z₃. 210 | 211 | # ╔═╡ 6fb12d46-9313-11eb-3755-f75318201c67 212 | md" This is not standard across programming languages. In other languages the operations performed will alter the original x₃. In order to do this in Julia, we have to use the `views` macro." 213 | 214 | # ╔═╡ 98ada18e-9313-11eb-1b00-a7df44a94629 215 | @views y₃ = x₃[1:2, 2:3] 216 | 217 | # ╔═╡ b4b7fe88-9313-11eb-1360-eda276fd3048 218 | y₃[2, 2] = 1.0 219 | 220 | # ╔═╡ c2ec5cba-9313-11eb-3a7f-45268de96491 221 | y₃ 222 | 223 | # ╔═╡ c63186d4-9313-11eb-0c5c-f93db7a91c3d 224 | x₃ # Look at the value of `1` in the 2nd row and third column. This is different from our original matrix. 225 | 226 | # ╔═╡ 44cd0f9a-9314-11eb-375e-2994eee141b8 227 | md" Now for the somewhat confusing part. In the case of subsetting we have that a copy is created, but if you use equality between variables (arrays), then we have that both variables point to the same data. They are allocated to the same place in memory. " 228 | 229 | # ╔═╡ 81cfcd24-9314-11eb-32ae-55253c36edee 230 | w₃ = x₃ 231 | 232 | # ╔═╡ 98f43312-9314-11eb-3442-33b1fecc4542 233 | pointer(w₃), pointer(x₃) # Points to same data 234 | 235 | # ╔═╡ b6647ccc-9314-11eb-3c5e-236ba616007e 236 | md" If we were to change w₃ in any way, it would also change x₃." 237 | 238 | # ╔═╡ cd203af2-9314-11eb-08a8-a5eb297100d2 239 | w₃[:, 1] .= 0 240 | 241 | # ╔═╡ dd873382-9314-11eb-2890-038d9bb37b5a 242 | x₃ 243 | 244 | # ╔═╡ e684a78a-9314-11eb-01cf-d3f8eb0b9129 245 | md" If we want to create a copy of x₃ so that we can work with the newly created variable and not alter the original value of x₃, then we can use the `copy` function." 246 | 247 | # ╔═╡ 12a4536a-9315-11eb-0c2e-0dbf2ba21af1 248 | v₃ = copy(x₃) 249 | 250 | # ╔═╡ 233e7d4a-9315-11eb-38a0-19744474c3e7 251 | pointer(v₃), pointer(x₃) # Pointing to different data 252 | 253 | # ╔═╡ 37862b4c-9315-11eb-3e9e-b36398d242ee 254 | md" The general lesson is that subsetting creates a `copy`, and setting arrays equal to each other creates a `view`. If you are aware of these then you won't have a problem. " 255 | 256 | # ╔═╡ ad4bc944-96f7-11eb-3c46-1f42cb700c68 257 | md" #### Special matrices " 258 | 259 | # ╔═╡ 70d37008-9705-11eb-17ac-15f8a398eb86 260 | md" There are some special arrays in Julia that we need take care in using. As always, we need to be careful about types in Julia. Consider the creation of a diagonal matrix." 261 | 262 | # ╔═╡ 9ae75b2a-9705-11eb-1e0e-5d2ca6c0407f 263 | d₁ = [1.0, 2.0] 264 | 265 | # ╔═╡ a1cfecfe-9705-11eb-2ea5-2bcdda8c123d 266 | d₂ = Diagonal(d₁) 267 | 268 | # ╔═╡ b62e71e8-9705-11eb-27d1-2b8e7fd1bf4f 269 | md" We observe that d₂ is not a 2-dimensional array as we would expect. The type is something completely different. Julia does this because this type is more efficient to store and to use in arithmetic and matrix operations. We can perform the same operations as before, but be careful to note that this is not a **dense** matrix. " 270 | 271 | # ╔═╡ 1146394e-9706-11eb-08be-cd9360651d26 272 | md" Another interesting example is that of the identity matrix. Let us say that we wanted to subtract the identity marix from a 2-dimensional array. We could do it in one of two ways. " 273 | 274 | # ╔═╡ 1e29435e-9706-11eb-1847-9b045e41ac71 275 | d₃ = [1.0 2.0; 3.0 4.0] 276 | 277 | # ╔═╡ 3969bd2e-9706-11eb-3c87-8b4ae3261186 278 | d₃ - Diagonal([1.0, 1.0]) 279 | 280 | # ╔═╡ 7b8586a2-9706-11eb-3062-df72a0a683c9 281 | d₃ - I # Note we didn't specify dimension of I 282 | 283 | # ╔═╡ 80e5300c-9706-11eb-393a-6d4dba078567 284 | typeof(I) 285 | 286 | # ╔═╡ 8e1b1ffc-9706-11eb-14d3-73f5ae17f967 287 | md" The identity matrix is a strange type that we have not encountered before. It is much more general than the method we employed and also more powerful as it can be applied in many different situations." 288 | 289 | # ╔═╡ e846ce68-96f7-11eb-37a5-b706a6979c63 290 | md" ### Basic operations " 291 | 292 | # ╔═╡ 4adb0436-9702-11eb-3583-397161d0d7e7 293 | md" Before we talk about systems of linear equations it might be useful to specify some of the basic linear algebra operations that we might encounter." 294 | 295 | # ╔═╡ 606ed3a4-9702-11eb-1396-6df331c01343 296 | x₄ = randn(5) 297 | 298 | # ╔═╡ 24681522-9703-11eb-33ac-15006eddeb11 299 | y₄ = randn(5) 300 | 301 | # ╔═╡ 6a7d20b6-0909-41dd-bd6b-70ff9c306803 302 | x₃ * x₃ # Normal matrix multiplication 303 | 304 | # ╔═╡ c82fc1d7-96d2-4d7d-90dd-8cd4816d9a1e 305 | x₃ .* x₃ # Element by element multiplication 306 | 307 | # ╔═╡ 6a6690ea-9702-11eb-0ee4-0b7ffb0b982b 308 | norm(x₄) # Provides the L2 norm 309 | 310 | # ╔═╡ 7f529b0c-9702-11eb-083a-71a10e65776c 311 | sqrt(sum(abs2, x₄)) # This is the L2 norm 312 | 313 | # ╔═╡ 96e43f00-9702-11eb-1244-df4c077349c7 314 | md" We might want to also think about calculating dot products. This can be done in the following way: " 315 | 316 | # ╔═╡ 51fc430a-9703-11eb-0595-19e9e6a75785 317 | dot(x₄, y₄) # x₄' * y₄ 318 | 319 | # ╔═╡ ffc56698-9702-11eb-3ab8-0baffe0aa914 320 | x₄'y₄ # Same answer as above 321 | 322 | # ╔═╡ b068662e-9703-11eb-13e3-c5898705e274 323 | md" Below is some other useful information that we might want to gather from a matrix. " 324 | 325 | # ╔═╡ 7bdfe3e8-9703-11eb-068d-398708020f10 326 | tr(x₃) # Computes the trace of the matrix 327 | 328 | # ╔═╡ 97061304-9703-11eb-07f0-b14fbf0fc3e6 329 | det(x₃) # Computes the determinant of the matrix 330 | 331 | # ╔═╡ a68db73c-9703-11eb-2bb4-7bbe725c4e3b 332 | rank(x₃) # Computes the rank of the matrix 333 | 334 | # ╔═╡ ce19b2b7-ea03-407b-afd3-ccb9489ff06e 335 | md" ### Matrices as maps " 336 | 337 | # ╔═╡ 29f485ca-9bb5-4444-a6a4-ecb533d4c3d1 338 | md" Thinking about matrices as maps or transformations is my preferred way to deal with the topic. It is more general, but also more powerful. One can view an $n \times k$ matrix as a function $f(x) = Ax$ that maps $x \in \mathbb{R}^{k}$ into $Ax \in \mathbb{R}^{n}$. This function $f: \mathbb{R}^{k} \rightarrow \mathbb{R}^{n}$ is considered **linear** if for scalars $\alpha, \beta$: 339 | 340 | $f(\alpha x + \beta y) = \alpha f(x) + \beta f(y)$ 341 | 342 | Below we show the definition of linear transformation and then some other interesting linear transformations that are often used in linear algebra. " 343 | 344 | # ╔═╡ 302f0117-3d5d-4d84-b58b-f5b7485489f0 345 | begin 346 | lin(a, b, c, d) = ((x, y),) -> ( a * x + b * y, c * x + d * y ) 347 | lin(A) = v -> A * [v...] # linear algebra version using matrix multiplication 348 | end 349 | 350 | # ╔═╡ 558bb7fc-d71d-4894-8748-778e9bce7c6f 351 | lin(x₃)([1, 2, 3]) 352 | 353 | # ╔═╡ caf7a9d3-3508-42a4-bcfd-a5ce2910f818 354 | begin 355 | id((x,y)) = [x, y] 356 | 357 | scalex(α) = ((x, y),) -> [α*x, y] 358 | scaley(α) = ((x, y),) -> [x, α*y] 359 | scale(α) = ((x, y),) -> [α*x, α*y] 360 | 361 | swap((x,y)) = [y, x] 362 | flipy((x,y)) = [x, -y] 363 | 364 | rotate(θ) = ((x, y),) -> [cos(θ)*x + sin(θ)*y, -sin(θ)*x + cos(θ)*y] 365 | shear(α) = ((x, y),) -> [x + α*y, y] 366 | end 367 | 368 | # ╔═╡ 5f9b9510-8e39-4c76-8b4b-4d759e2db60f 369 | md" You can take some time to play around with the transformations. In this case the input needs to be a vector with two entries. I applied some of these methods to the vector `[1, 2]` below. " 370 | 371 | # ╔═╡ 11d14fe1-ecb3-417a-9299-e0c34b4d64f3 372 | id([1, 2]) 373 | 374 | # ╔═╡ 891a5ee7-453e-4c90-9f26-5129f37c568b 375 | swap([1, 2]) 376 | 377 | # ╔═╡ 487e7c23-b327-43cf-9daf-1087300cc3ca 378 | scale(5)([1, 2]) 379 | 380 | # ╔═╡ 3748bd90-1acd-4411-960e-b25ec2178cc5 381 | scalex(5)([1, 2]) 382 | 383 | # ╔═╡ 6f0c0bc4-96d1-11eb-1cd9-9172bb9f042c 384 | md" # Solving systems of linear equations" 385 | 386 | # ╔═╡ 83ae1458-96d3-11eb-2e21-a3be23f7b874 387 | md" One of the most basic tasks in numerical analysis is to solve the system of linear equations, which can be represented with the following matrix-vector notation. 388 | 389 | $$\textbf{Ax = b}$$ 390 | 391 | where $\textbf{A}$ is a $n \times n$ matrix, $\textbf{b}$ is a vector of length $n$ and $\textbf{x}$ is a vector of length $n$." 392 | 393 | # ╔═╡ 45b2161a-96db-11eb-046a-079f3ddfcee9 394 | md" Judd (1998) states that there are three reasons to solve linear equations. 395 | 396 | 1. Important class of problems in themselves. 397 | 2. Linear equations are almost the only problem we know how to solve directly. 398 | 3. Many ideas used in this section are applicable to more general problems in later sessions. " 399 | 400 | # ╔═╡ 2fbbf6ce-96dc-11eb-28fd-a531a03c2a72 401 | md" For this session we will first discuss **direct methods** for solving linear equations. We follow that with a quick discussion on the condition number for a linear system and then we cover **iterative methods** for solving systems of equations. " 402 | 403 | # ╔═╡ 67607a1c-96e3-11eb-3acb-55a989e7efb4 404 | md" ### Direct methods" 405 | 406 | # ╔═╡ 2f46eecc-96f5-11eb-3f35-19de6bd828be 407 | md" There are several direct methods for solving linear equations. Direct methods involve factorisations of the matrix of interest. We will focus on Gaussian elimation (GE) and lower-upper (LU) decomposition. However, one can also look at QR decomposition and singular value decomposition (SVD). I don't believe we will have time for the last two methods, but will perhaps in passing mention how they operate. 408 | 409 | These direct methods are best applied to *dense* and relatively small $\textbf{A}$ matrices." 410 | 411 | # ╔═╡ 86606d6e-96f5-11eb-0991-a7ab19525fde 412 | md" #### Exploiting structure --> triangular systems " 413 | 414 | # ╔═╡ e8ce31d0-9056-48c3-a3d8-0aae4b99eb33 415 | md" We want to solve $\textbf{Ax = b}$. In most cases this means solving $\mathbf{x = A^{-1}b}$. This means that we need to find the inverse of a matrix, which is often hard to do. In the numerical world we **almost never compute an inverse**. The process of finding the solution through an inverse is slower than solving the linear system of equations. 416 | 417 | The idea in this section is to the turn the original problem into one that is easy to solve. We would like to transform our $\textbf{A}$ matrix into a structure that can be easily solved. One such representation is the triangular system. Other matrices that are easy to solve include permutation and orthogonal matrices. Below is a representation of a lower triangular matrix. 418 | 419 | $$\left(\begin{array}{cccc}a_{11} & 0 & \cdots & 0 \\ a_{21} & a_{22} & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ a_{n 1} & a_{n 2} & \cdots & a_{n n}\end{array}\right)\left(\begin{array}{c}x_{1} \\ x_{2} \\ \vdots \\ x_{n}\end{array}\right)=\left(\begin{array}{c}b_{1} \\ b_{2} \\ \vdots \\ b_{n}\end{array}\right)$$ 420 | 421 | The reason we want this strucuture, is that we can then solve by **forward substitution**, which is represented as follows: 422 | 423 | $\begin{aligned} x_{1} &=b_{1} / a_{11} \\ x_{2} &=\left(b_{2}-a_{21} x_{1}\right) / a_{22} \\ x_{3} &=\left(b_{3}-a_{31} x_{1}-a_{32} x_{2}\right) / a_{33} \\ & \quad \vdots \\ x_{n} &=\left(b_{n}-a_{n 1} x_{1}-a_{n 2} x_{2}-\cdots-a_{n, n-1} x_{n-1}\right) / a_{n n} \end{aligned}$" 424 | 425 | # ╔═╡ 34ad7ce4-0e9f-40eb-9424-c53ee764e5b9 426 | md" One can code this forward substitution by hand using a `for loop` as follows." 427 | 428 | # ╔═╡ f3a02044-f490-4273-8019-8938beba724d 429 | function forwardsub(a,b) 430 | 431 | n = size(a,1) 432 | x = zeros(n) 433 | x[1] = b[1]/a[1,1] 434 | for i = 2:n 435 | s = sum( a[i,j]*x[j] for j=1:i-1 ) 436 | x[i] = ( b[i] - s ) / a[i,i] 437 | end 438 | 439 | return x 440 | end 441 | 442 | # ╔═╡ 120cbbfc-94f3-4187-b8ca-d553e943f9a0 443 | md" Now let us use our function `forwardsub` to solve for a triangular system." 444 | 445 | # ╔═╡ fb1c0b79-fd47-4beb-b2cb-0fc671f08164 446 | begin 447 | Random.seed!(123); # Set seed for reproducibility 448 | n₁ = 5; 449 | A₁ = randn(n₁, n₁); 450 | b₁ = randn(n₁); 451 | end 452 | 453 | # ╔═╡ 19af2999-2502-4782-9396-c7d29b2f59cf 454 | A₁ 455 | 456 | # ╔═╡ 376f2364-7483-4739-8005-bbaac18d649b 457 | L₁ = tril(A₁) # Full triangular matrix 458 | 459 | # ╔═╡ 7f85de41-ec85-486f-827f-ea08929e9ab5 460 | md" We can use the `LowerTriangular` command to create a copy of the lower triangular portion of the original $\textbf{A}$ matrix." 461 | 462 | # ╔═╡ a15b1ed6-7270-4feb-8fcc-498249e5ff91 463 | L₂ = LowerTriangular(A₁) 464 | 465 | # ╔═╡ c0290bf7-96c7-42ef-80d1-35f6f88f08eb 466 | b₁ 467 | 468 | # ╔═╡ 6a23242c-ed7f-4f45-a1fa-3289f86f7156 469 | md" We have written our function to solve this problem. Now given that you have a triangular structure, how would you go about solving this with some of the included functions in Julia? Using the `\` operator in Julia will solve the problem using forward substitution if the system is lower triangular. It detects that there is a lower triangular structure and dispacthes to a basic linear algebra subprogram (BLAS) routine to compute. In this case the subroutine is most likely [trsv](https://www.netlib.org/lapack/explore-html/d6/d96/dtrsv_8f.html). Let us compare the two methods." 470 | 471 | # ╔═╡ ba9515e2-eb87-441c-ad54-ab018fc74625 472 | forwardsub(L₂, b₁) 473 | 474 | # ╔═╡ c5188bbe-1d2f-4964-aa99-0a151118c4af 475 | L₂ \ b₁ 476 | 477 | # ╔═╡ ff3d034c-fd35-47e1-819a-c048ea5f2ec4 478 | md" We get the same answer. So is the Julia routine faster?" 479 | 480 | # ╔═╡ b8fb29ee-f244-4060-ba85-6d0518426691 481 | @benchmark forwardsub(L₂, b₁) 482 | 483 | # ╔═╡ e279a91e-5fab-4b73-8f63-610750c2fd1d 484 | @benchmark L₂ \ b₁ 485 | 486 | # ╔═╡ af09ca7e-fcab-48fe-b61b-115edaa814d7 487 | md" #### Gaussian elimination " 488 | 489 | # ╔═╡ 68582594-c03b-4c1b-ad53-3549cedc1e8b 490 | md" We have encountered the `\` operator before in the case of a triangular system. However, what happens when we call this operator on solve a linear equation when the system is not triangular? In other words, what happens when we call `A \ b` to solve a linear equation when the matrix `A` is square? Note that when the matrix is **not square** we will get the least squares solution to the problem. " 491 | 492 | # ╔═╡ 6b82fef2-e19a-4551-88b4-6093d6d7ff7f 493 | A₂ = [2.0 1.0 -1.0; -3.0 -1.0 2.0; -2.0 1.0 2.0] 494 | 495 | # ╔═╡ f29371ee-4e2e-48bc-95a6-5c52820504ba 496 | b₂ = [8.0, -11.0, -3.0] 497 | 498 | # ╔═╡ b0dd755c-3793-44fe-b6d9-fce3b3289564 499 | A₂ \ b₂ 500 | 501 | # ╔═╡ f89e0088-dbc4-43df-8159-39184b735930 502 | md" In order to understand the process of Gaussian elimination, you have to know what an elementary matrix represents. For those who know the procedure feel free to move on to the example. An elementary matrix is an identity matrix with the zero in position $(j, k)$ replaced by a value of $c$. 503 | 504 | $\mathbf{E}_{j k}(c)=\left(\begin{array}{ccccccc}1 & & & & & & \\ & \ddots & & & & & \\ & & 1 & & & & \\ & & & \ddots & & & \\ & & c & & 1 & & \\ & & & & & \ddots & \\ & & & & & & 1\end{array}\right)=\mathbf{I}+c \mathbf{e}_{j} \mathbf{e}_{k}^{T}$ 505 | 506 | 507 | The term $\mathbf{E}_{j k}(c)$ left multiplies a matrix $\mathbf{X}$ to replace its $j$-th row $\mathbf{x}_{j}$ by $c\mathbf{x_k} + \mathbf{x_j}$: 508 | 509 | $\mathbf{E}_{j k}(c) \times \mathbf{X}=\mathbf{E}_{j k}(c) \times\left(\begin{array}{llll}\ldots & \mathbf{x}_{k} & \ldots \\ \cdots & \mathbf{x}_{j} & \cdots\end{array}\right)=\left(\begin{array}{lll}\ldots & \mathbf{x}_{k \cdot} & \ldots \\ \cdots & c \mathbf{x}_{k}+\mathbf{x}_{j} & \ldots\end{array}\right)$ 510 | 511 | Gaussian elimination effectively applies a sequence of elementary matrices to transform the linear system that we are provided to an upper triangular structure $\mathbf{U}$. 512 | 513 | $$\begin{aligned} \mathbf{E}_{n, n-1}\left(c_{n, n-1}\right) \cdots \mathbf{E}_{21}\left(c_{21}\right) \mathbf{A} \mathbf{x} &=\mathbf{E}_{n, n-1}\left(c_{n, n-1}\right) \cdots \mathbf{E}_{21}\left(c_{21}\right) \mathbf{b} \\ \mathbf{U x} &=\mathbf{b}_{\mathrm{new}} \end{aligned}$$" 514 | 515 | # ╔═╡ 10e36444-e747-4cde-a51c-1e57d3a6cb9e 516 | md" To illustrate the procedure, let us show the steps in the proces. For the first column we construct our elementary matrix with the hope of eliminating the `-3.0` in the `(2, 1)` position of the $A_2$ matrix. Using a value of `1.5` in the `(2, 1)` position of the $E_{21}$ elementary matrix provides us with the required result, as we show below." 517 | 518 | # ╔═╡ 6e278a30-363d-413b-8c7e-833b9b0d1047 519 | E21 = [1.0 0.0 0.0; 1.5 1.0 0.0; 0.0 0.0 1.0] 520 | 521 | # ╔═╡ 73132b4b-f7b8-4b19-8abe-50bd2844524e 522 | md" How did we get to this value of `1.5`? Maybe the following bit of code will help. " 523 | 524 | # ╔═╡ 2f35943d-311c-4e4f-8b07-1ca9062961a1 525 | mult21 = A₂[2, 1]/A₂[1, 1] # Can you follow the logic here? 526 | 527 | # ╔═╡ d328e1eb-4feb-4e40-9835-bf5e64beb263 528 | md" We left multiply $E_{21}$ with $A_2$ to replace its second row `[-3.0, -1.0, 2.0]` by `1.5*[2.0, 1.0, -1.0] + [-3.0, -1.0, 2.0]`. This will give us the following." 529 | 530 | # ╔═╡ fba688bb-a451-450b-bc1a-9002e090412c 531 | E21 * A₂ # This gives us a zero in the (2, 1) position. 532 | 533 | # ╔═╡ 30216472-4160-459d-8796-0b2fa1e9b20e 534 | md" We still need a zero in the `(3, 1)` and `(3, 2)` position. All steps for the process are shown below. " 535 | 536 | # ╔═╡ d73e2a8d-f2df-4353-a4a8-141d34af93e8 537 | E31 = [1.0 0.0 0.0; 0.0 1.0 0.0; 1.0 0.0 1.0] 538 | 539 | # ╔═╡ 3396b7ff-2022-4bda-a5cc-98d330f6b103 540 | E31 * E21 * A₂ # This gives us a zero in the (2, 1) and (3, 1) position. 541 | 542 | # ╔═╡ 222532b1-fdc3-4aa8-ae40-48fdc54c9e26 543 | E32 = [1.0 0.0 0.0; 0.0 1.0 0.0; 0.0 -4.0 1.0] 544 | 545 | # ╔═╡ b6cc62b8-1f4b-4fdc-9376-3365908cf428 546 | E32 * E31 * E21 * A₂ # We have our upper triangular structure. 547 | 548 | # ╔═╡ 5a3e13a9-78a6-46e0-bec5-5fa18b9db13d 549 | md" We performed our transformation one column at a time. If we combine the elementary matrix operations for each column into one operator, that is referred to as a Gauss transformation. In general for the first column the formula would be: 550 | 551 | $\mathbf{M}_{1}=\mathbf{E}_{n 1}\left(c_{n 1}\right) \cdots \mathbf{E}_{31}\left(c_{31}\right) \mathbf{E}_{21}\left(c_{21}\right)$ 552 | 553 | In our case we have that $\mathbf{M}_{1} = \mathbf{E}_{31}\left(c_{31}\right) \mathbf{E}_{21}\left(c_{21}\right)$ and $\mathbf{M}_{2} = \mathbf{E}_{32}\left(c_{32}\right)$." 554 | 555 | # ╔═╡ 153453d8-2de0-4a40-86b9-24cf83e2d8ee 556 | M1 = E31 * E21 557 | 558 | # ╔═╡ 8ee0c629-8c1e-4d61-b9fe-d2fe3a9543ed 559 | M2 = E32 560 | 561 | # ╔═╡ bbfe4b6e-8b72-4f6b-b516-1b8838adbcee 562 | md" #### LU factorisation " 563 | 564 | # ╔═╡ 8f7849aa-6302-4feb-b6c2-a4b27d3d4bd8 565 | md" In essence Gaussian elimination does $\mathbf{M}_{n-1} \cdots \mathbf{M}_{1} \mathbf{A}=\mathbf{U}$. So if we let $\mathbf{L}=\mathbf{M}_{1}^{-1} \cdots \mathbf{M}_{n-1}^{-1}$ then the elimination process leads to a factorisation $\mathbf{A}=\mathbf{L} \mathbf{U}$ where $\mathbf{L}$ is unit lower triangular and $\mathbf{U}$ is upper triangular. This $\mathbf{L} \mathbf{U}$ factorisation reduces any linear system to two triangular ones. So if we want to to solve $\textbf{Ax = b}$ the steps are as follows. 566 | 567 | 1. Factor $\mathbf{A}=\mathbf{L} \mathbf{U}$ using Gaussian elimination. 568 | 2. Solve $\textbf{Lz = b}$ for $\textbf{z}$ using forward substitution. 569 | 3. Solve $\textbf{Ux = z}$ for $\textbf{x}$ using backward substitution. 570 | 571 | Below we have a function that shows how this factorisation might take place. " 572 | 573 | # ╔═╡ eb80ec1a-5728-48e0-9836-2270ce4ed87a 574 | function lufact(A) 575 | 576 | n = size(A,1) 577 | L = Matrix(Diagonal(ones(n))) 578 | U = float(copy(A)) 579 | 580 | # Gaussian elimination 581 | for j = 1:n-1 582 | for i = j+1:n 583 | L[i,j] = U[i,j] / U[j,j] # row multiplier 584 | U[i,j:n] -= L[i,j]*U[j,j:n] 585 | end 586 | end 587 | 588 | return L,triu(U) 589 | end 590 | 591 | # ╔═╡ 7b37c063-8142-473f-9d71-0b5edada4e20 592 | md" For a dense matrix without any knowledge on its structure (not known to be tridiagonal, symmetric, etc. ) this LU decomposition is the standard procedure that will be used to solve the system. It utilises the speed of forward and backward substitution. Let us take a closer look at how Julia does this. " 593 | 594 | # ╔═╡ acd812ce-19f1-42f2-80a0-4b0f4cca006f 595 | Af = factorize(A₂) 596 | 597 | # ╔═╡ 5f459761-faa9-492e-8fe3-b95634a39c0c 598 | md" Here we have the LU factorisation **with pivoting**. We can also directly call for the L and U components. " 599 | 600 | # ╔═╡ 64979eaa-e551-4da3-9203-ee75bc5d64d2 601 | L, U = lu(A₂, Val(false)) 602 | 603 | # ╔═╡ 70ce2499-3b4a-4213-a6de-d3b9454a62fa 604 | A₂ ≈ L * U 605 | 606 | # ╔═╡ bf68439d-d1f8-437b-b851-bcfd65ab13ea 607 | md" #### Cholesky decomposition " 608 | 609 | # ╔═╡ 6405964a-f5e2-471e-a054-adcf0e5db512 610 | md" The LU decomposition is not often used in statistics, because statisticians and econometricians often deal with positive (semi)definite matrices. If our matrix $A$ is real, symmetric, and positive definite then a Cholesky decomposition is a form of LU decomposition where $L = U'$, so that $A = LL'$. This factorisation is used in many application, especially with relation to time series analysis and control theory. 611 | 612 | As example, think of linear regression. Our normal equation is 613 | 614 | $\mathbf{X}^{T} \mathbf{X} \beta=\mathbf{X}^{T} \mathbf{y}$ 615 | 616 | In this case the coefficient matrix $\mathbf{X}^{T} \mathbf{X}$ is symmetric and positive semidefinite. We want to be able to exploit this structure. Let us explore Cholesky decomposition with a few examples. " 617 | 618 | # ╔═╡ edd75ea3-84dc-45f7-adec-540b7984aaa9 619 | x₅ = rand(1.0:9.0,4,4) # Very unlikely to be symmetric and positive definite 620 | 621 | # ╔═╡ feebcf59-527e-4b49-87f9-0090002e9454 622 | A₃ = Symmetric(x₅) # Easy way to get symmetry, but not always positive definite 623 | 624 | # ╔═╡ 9eb49bae-fbf7-49e1-b8aa-3b939d577dee 625 | cholesky(A₃) 626 | 627 | # ╔═╡ eea1458e-7fa1-4772-9dba-246d3eeeda9c 628 | x₆ = x₅'x₅ # Easy to manufacture an SPD matrix to try Cholesky factorisation 629 | 630 | # ╔═╡ b6a10960-4e3c-4fef-93ed-118dbd3493a7 631 | cholesky(x₆) 632 | 633 | # ╔═╡ a42329cc-5a69-4ba2-97e0-8e45b7fd9a67 634 | md" We won't go into too much detail on Cholesky decomposition in this section, but let us illustrate how much faster the process can be with a real world example. Consider the multivariate normal density where the variance-covariance matrix is positive definite. We want to utilise this structure. The $\text{MVN}(0, \Sigma)$ with $\Sigma$ the variance-covariance matrix, has the following explicit form. 635 | 636 | $-\frac{n}{2} \log (2 \pi)-\frac{1}{2} \log \operatorname{det} \Sigma-\frac{1}{2} \mathbf{y}^{T} \Sigma^{-1} \mathbf{y}$ 637 | 638 | The costly computations here are the determinant of $\Sigma$, inverse of $\Sigma$ and computation of the quadratic form. If you were not aware of the structure here, you might do the following. 639 | 640 | **Method 1 (naive)**: Compute $\Sigma^{-1}$, compute quadratic form, compute determinant. 641 | 642 | **Method 2 (using structure)**: Compute $\Sigma = \mathbf{LL}'$, solve $\mathbf{Lx = y}$ by forward substitution, compute quadratic form $\mathbf{x'x}$ and compute determinant from Cholesky factor." 643 | 644 | 645 | # ╔═╡ 095f1ce7-e626-453e-9d7e-cf0af284d7ed 646 | # Method 1 647 | function logpdf_mvn_1(y::Vector, Σ::Matrix) 648 | n = length(y) 649 | - (n//2) * log(2π) - (1//2) * logdet(Symmetric(Σ)) - (1//2) * transpose(y) * inv(Σ) * y 650 | end 651 | 652 | # ╔═╡ ac31e2a8-4c91-44f0-85cb-dc4751fd1c62 653 | # Method 2 654 | function logpdf_mvn_2(y::Vector, Σ::Matrix) 655 | n = length(y) 656 | Σchol = cholesky(Symmetric(Σ)) 657 | - (n//2) * log(2π) - (1//2) * logdet(Σchol) - (1//2) * abs2(norm(Σchol.L \ y)) 658 | end 659 | 660 | # ╔═╡ e803605e-c56e-442e-a60f-707a07dc4009 661 | begin 662 | Random.seed!(123); # seed 663 | 664 | n = 1000; 665 | # a pd matrix 666 | Σ = convert(Matrix{Float64}, Symmetric([i * (n - j + 1) for i in 1:n, j in 1:n])); 667 | y = rand(MvNormal(Σ)); # one random sample from N(0, Σ) 668 | 669 | # at least they should give the same answer 670 | logpdf_mvn_1(y, Σ); 671 | logpdf_mvn_2(y, Σ); 672 | end 673 | 674 | # ╔═╡ 9056fa71-a624-4430-9af6-1c9dbd8df961 675 | @benchmark logpdf_mvn_1(y, Σ) 676 | 677 | # ╔═╡ 557eb079-b812-4fc6-b78a-2d933ef80215 678 | @benchmark logpdf_mvn_2($y, $Σ) 679 | 680 | # ╔═╡ 67b3ec44-f9b8-42d6-828b-bb05007aff27 681 | md" One can also look at other decompositions such as the QR and spectral decomposition. We won't have time to cover these topics, but they are quite important. " 682 | 683 | # ╔═╡ 8139e91c-96e3-11eb-1d43-7d9502ac6d91 684 | md" ### Iterative solvers " 685 | 686 | # ╔═╡ ce083a66-96f5-11eb-1e1c-639e4764cc51 687 | md" There are many different iterative methods, we will focus on the Jacobi method, Gauss-Seidel method and successive over-relaxation (SOR) in this section. Conjugate-gradient methods will also be briefly mentioned. 688 | 689 | These iterative methods are best applied to large, *sparse*, structured linear systems." 690 | 691 | # ╔═╡ c468cc76-97d3-4305-b575-e1aa352ec0ff 692 | md" #### Jacobi method " 693 | 694 | # ╔═╡ d661036f-ea13-4e4d-95da-5cfa4786c786 695 | md" #### Gauss-Seidel method " 696 | 697 | # ╔═╡ e75b1b83-7a97-4b8f-9be0-b72a5d09d713 698 | md" #### Successive over-relaxation " 699 | 700 | # ╔═╡ dbc150ba-c617-4ab4-96b2-f6f6d208a47b 701 | md" #### Conjugate-gradient methods " 702 | 703 | # ╔═╡ f5643e42-9504-4ea9-82d5-fa7574da88b1 704 | md"### Numerical linear algebra (optional) " 705 | 706 | # ╔═╡ d5f1b957-d9c8-4ad7-aa36-3ff818d69fde 707 | md" This section is a bit more advanced and is optional for those who do not care much about the topic. However, take note that you will need to invest some time in understanding these ideas at some point if you care about solving linear systems. The notes here follow the structure of [QuantEcon](https://julia.quantecon.org/tools_and_techniques/numerical_linear_algebra.html). There are three key principles when it comes to numerical linear algebra. 708 | 709 | 1. Identify structure in order to use specialised algorithms 710 | 2. Do not lose structure by appplying wrong numerical linear algebra operations at wrong times. 711 | 3. Understand the computational complexity of each algorithm, given structure." 712 | 713 | # ╔═╡ daac8a8b-294c-437a-859d-fe8c613e4b39 714 | md" #### Structure in matrices " 715 | 716 | # ╔═╡ a3bb44ae-f745-4cc9-a983-e019ea35c780 717 | md" #### Computational complexity " 718 | 719 | # ╔═╡ 7573a640-96e3-11eb-1214-070209074966 720 | md" #### Norms and condition numbers " 721 | 722 | # ╔═╡ Cell order: 723 | # ╟─796b0922-8c17-11eb-31e8-59d5b21ee32b 724 | # ╟─97dca378-8c17-11eb-1a9f-49d299180a72 725 | # ╟─8dd16592-8d9c-11eb-1adb-af30ea9f5bc5 726 | # ╟─d3a32206-96ff-11eb-0c21-953e0d446b50 727 | # ╟─cdcc50b0-8c18-11eb-3188-ffb91dcecee8 728 | # ╟─dc8e8004-8d95-11eb-30c0-33a66a0c3f6b 729 | # ╠═eea539ae-8d95-11eb-1a13-d704f50969c3 730 | # ╠═1eeb8d5c-8d96-11eb-0bc1-0162c420760f 731 | # ╟─e9140e2a-8d97-11eb-3a2c-79fad99882ea 732 | # ╠═784d31a8-8d9a-11eb-02bc-a3a24bcb564c 733 | # ╟─3329945f-d07f-4aa8-8715-b9cdebb5fd22 734 | # ╠═61132429-1e0a-491a-b1e8-66dc45e72110 735 | # ╟─ce128ae2-8d9b-11eb-0399-cda8550d4524 736 | # ╠═98dbd9c8-8d9b-11eb-009d-b93e1b869285 737 | # ╠═ff747db4-8d9b-11eb-3a10-3314a843e679 738 | # ╟─b386f1dc-8d9a-11eb-2bb8-a58a56b5a85b 739 | # ╠═cb7dce80-8d9a-11eb-1f83-fb79238361e1 740 | # ╠═54db62f4-8d9b-11eb-34d6-9f4d16b251de 741 | # ╠═1b9b6594-8d9d-11eb-375a-79652da9dee1 742 | # ╠═2ba16772-8d9d-11eb-0a26-c556fb0240aa 743 | # ╠═2f5d84f6-9700-11eb-3dca-799c96c6b609 744 | # ╟─438e6cba-9700-11eb-2c73-339e72e703cb 745 | # ╠═8f86a65a-9700-11eb-1633-95b7ef7e7295 746 | # ╠═a1cd647e-92f1-11eb-0ddb-fdc6a622bb8e 747 | # ╠═af513998-92f1-11eb-16c2-3bd34fe8a231 748 | # ╠═859cee86-8d9d-11eb-2993-bb3f3d748df6 749 | # ╟─dfa715e2-8d9c-11eb-29e3-7dad0fad127f 750 | # ╟─cd94ab08-8d9c-11eb-2a76-673456a371ef 751 | # ╟─9bd1329e-8d9c-11eb-1751-fd348630580e 752 | # ╠═ae7906d8-8d9c-11eb-3e39-4fcddb18b1d2 753 | # ╠═b28764ae-8d9c-11eb-10f7-8f4b2387665f 754 | # ╠═b7a8d21a-8d9c-11eb-106d-2f68dc163529 755 | # ╠═f29ef44a-8d9d-11eb-0dbe-d5cc7c1080db 756 | # ╠═e358ae06-becb-4d26-ab5a-2e3eee274e54 757 | # ╠═fb532bfe-8d9d-11eb-2a10-89d840f835df 758 | # ╠═16efc20a-8d9e-11eb-1819-47dd80edfc9b 759 | # ╠═08ef44e4-8da0-11eb-3d23-052a692e711f 760 | # ╠═40b31e3c-8d9e-11eb-0c87-5bf71827d188 761 | # ╠═58232b72-8d9e-11eb-0489-cfccbceb1e11 762 | # ╠═dab8d7f8-8d9e-11eb-0805-c7343db6c32b 763 | # ╠═3c9c9d0a-a13c-4e33-82b3-1d5cfec04c3f 764 | # ╠═72390509-65be-4508-802e-458869d49b23 765 | # ╠═e5bee5de-8d9e-11eb-12af-617d270d651a 766 | # ╟─e6c21a46-9311-11eb-3655-0dce4406e2c5 767 | # ╟─f03aece2-9311-11eb-1467-c73576cd3184 768 | # ╟─1398128c-9312-11eb-3f28-07be67646964 769 | # ╠═ff94ad36-9311-11eb-297d-5192bd1882ec 770 | # ╠═113271b0-9312-11eb-13c2-cd42aaf2ba53 771 | # ╠═60e1fce2-9312-11eb-19db-df30cb82005f 772 | # ╠═44e3c3c2-9312-11eb-34a4-e3a6b4e5d937 773 | # ╟─f2d1cce0-9312-11eb-0747-3f0c6f75c1c2 774 | # ╠═35d91f66-9313-11eb-075c-3ba0a8b38f60 775 | # ╠═47bd69a6-9313-11eb-0aff-0116148e2a69 776 | # ╠═551fc65e-9313-11eb-3043-516e2886485f 777 | # ╠═59639cac-9313-11eb-008e-9fd2113271e7 778 | # ╟─6fb12d46-9313-11eb-3755-f75318201c67 779 | # ╠═98ada18e-9313-11eb-1b00-a7df44a94629 780 | # ╠═b4b7fe88-9313-11eb-1360-eda276fd3048 781 | # ╠═c2ec5cba-9313-11eb-3a7f-45268de96491 782 | # ╠═c63186d4-9313-11eb-0c5c-f93db7a91c3d 783 | # ╟─44cd0f9a-9314-11eb-375e-2994eee141b8 784 | # ╠═81cfcd24-9314-11eb-32ae-55253c36edee 785 | # ╠═98f43312-9314-11eb-3442-33b1fecc4542 786 | # ╟─b6647ccc-9314-11eb-3c5e-236ba616007e 787 | # ╠═cd203af2-9314-11eb-08a8-a5eb297100d2 788 | # ╠═dd873382-9314-11eb-2890-038d9bb37b5a 789 | # ╟─e684a78a-9314-11eb-01cf-d3f8eb0b9129 790 | # ╠═12a4536a-9315-11eb-0c2e-0dbf2ba21af1 791 | # ╠═233e7d4a-9315-11eb-38a0-19744474c3e7 792 | # ╟─37862b4c-9315-11eb-3e9e-b36398d242ee 793 | # ╟─ad4bc944-96f7-11eb-3c46-1f42cb700c68 794 | # ╟─70d37008-9705-11eb-17ac-15f8a398eb86 795 | # ╠═9ae75b2a-9705-11eb-1e0e-5d2ca6c0407f 796 | # ╠═a1cfecfe-9705-11eb-2ea5-2bcdda8c123d 797 | # ╟─b62e71e8-9705-11eb-27d1-2b8e7fd1bf4f 798 | # ╟─1146394e-9706-11eb-08be-cd9360651d26 799 | # ╠═1e29435e-9706-11eb-1847-9b045e41ac71 800 | # ╠═3969bd2e-9706-11eb-3c87-8b4ae3261186 801 | # ╠═7b8586a2-9706-11eb-3062-df72a0a683c9 802 | # ╠═80e5300c-9706-11eb-393a-6d4dba078567 803 | # ╟─8e1b1ffc-9706-11eb-14d3-73f5ae17f967 804 | # ╟─e846ce68-96f7-11eb-37a5-b706a6979c63 805 | # ╟─4adb0436-9702-11eb-3583-397161d0d7e7 806 | # ╠═606ed3a4-9702-11eb-1396-6df331c01343 807 | # ╠═24681522-9703-11eb-33ac-15006eddeb11 808 | # ╠═6a7d20b6-0909-41dd-bd6b-70ff9c306803 809 | # ╠═c82fc1d7-96d2-4d7d-90dd-8cd4816d9a1e 810 | # ╠═6a6690ea-9702-11eb-0ee4-0b7ffb0b982b 811 | # ╠═7f529b0c-9702-11eb-083a-71a10e65776c 812 | # ╟─96e43f00-9702-11eb-1244-df4c077349c7 813 | # ╠═51fc430a-9703-11eb-0595-19e9e6a75785 814 | # ╠═ffc56698-9702-11eb-3ab8-0baffe0aa914 815 | # ╟─b068662e-9703-11eb-13e3-c5898705e274 816 | # ╠═7bdfe3e8-9703-11eb-068d-398708020f10 817 | # ╠═97061304-9703-11eb-07f0-b14fbf0fc3e6 818 | # ╠═a68db73c-9703-11eb-2bb4-7bbe725c4e3b 819 | # ╟─ce19b2b7-ea03-407b-afd3-ccb9489ff06e 820 | # ╟─29f485ca-9bb5-4444-a6a4-ecb533d4c3d1 821 | # ╠═302f0117-3d5d-4d84-b58b-f5b7485489f0 822 | # ╠═558bb7fc-d71d-4894-8748-778e9bce7c6f 823 | # ╠═caf7a9d3-3508-42a4-bcfd-a5ce2910f818 824 | # ╟─5f9b9510-8e39-4c76-8b4b-4d759e2db60f 825 | # ╠═11d14fe1-ecb3-417a-9299-e0c34b4d64f3 826 | # ╠═891a5ee7-453e-4c90-9f26-5129f37c568b 827 | # ╠═487e7c23-b327-43cf-9daf-1087300cc3ca 828 | # ╠═3748bd90-1acd-4411-960e-b25ec2178cc5 829 | # ╟─6f0c0bc4-96d1-11eb-1cd9-9172bb9f042c 830 | # ╟─83ae1458-96d3-11eb-2e21-a3be23f7b874 831 | # ╟─45b2161a-96db-11eb-046a-079f3ddfcee9 832 | # ╟─2fbbf6ce-96dc-11eb-28fd-a531a03c2a72 833 | # ╟─67607a1c-96e3-11eb-3acb-55a989e7efb4 834 | # ╟─2f46eecc-96f5-11eb-3f35-19de6bd828be 835 | # ╟─86606d6e-96f5-11eb-0991-a7ab19525fde 836 | # ╟─e8ce31d0-9056-48c3-a3d8-0aae4b99eb33 837 | # ╟─34ad7ce4-0e9f-40eb-9424-c53ee764e5b9 838 | # ╠═f3a02044-f490-4273-8019-8938beba724d 839 | # ╟─120cbbfc-94f3-4187-b8ca-d553e943f9a0 840 | # ╠═fb1c0b79-fd47-4beb-b2cb-0fc671f08164 841 | # ╠═19af2999-2502-4782-9396-c7d29b2f59cf 842 | # ╠═376f2364-7483-4739-8005-bbaac18d649b 843 | # ╟─7f85de41-ec85-486f-827f-ea08929e9ab5 844 | # ╠═a15b1ed6-7270-4feb-8fcc-498249e5ff91 845 | # ╠═c0290bf7-96c7-42ef-80d1-35f6f88f08eb 846 | # ╟─6a23242c-ed7f-4f45-a1fa-3289f86f7156 847 | # ╠═ba9515e2-eb87-441c-ad54-ab018fc74625 848 | # ╠═c5188bbe-1d2f-4964-aa99-0a151118c4af 849 | # ╟─ff3d034c-fd35-47e1-819a-c048ea5f2ec4 850 | # ╠═b8fb29ee-f244-4060-ba85-6d0518426691 851 | # ╠═e279a91e-5fab-4b73-8f63-610750c2fd1d 852 | # ╟─af09ca7e-fcab-48fe-b61b-115edaa814d7 853 | # ╟─68582594-c03b-4c1b-ad53-3549cedc1e8b 854 | # ╠═6b82fef2-e19a-4551-88b4-6093d6d7ff7f 855 | # ╠═f29371ee-4e2e-48bc-95a6-5c52820504ba 856 | # ╠═b0dd755c-3793-44fe-b6d9-fce3b3289564 857 | # ╟─f89e0088-dbc4-43df-8159-39184b735930 858 | # ╟─10e36444-e747-4cde-a51c-1e57d3a6cb9e 859 | # ╠═6e278a30-363d-413b-8c7e-833b9b0d1047 860 | # ╟─73132b4b-f7b8-4b19-8abe-50bd2844524e 861 | # ╠═2f35943d-311c-4e4f-8b07-1ca9062961a1 862 | # ╟─d328e1eb-4feb-4e40-9835-bf5e64beb263 863 | # ╠═fba688bb-a451-450b-bc1a-9002e090412c 864 | # ╟─30216472-4160-459d-8796-0b2fa1e9b20e 865 | # ╠═d73e2a8d-f2df-4353-a4a8-141d34af93e8 866 | # ╠═3396b7ff-2022-4bda-a5cc-98d330f6b103 867 | # ╠═222532b1-fdc3-4aa8-ae40-48fdc54c9e26 868 | # ╠═b6cc62b8-1f4b-4fdc-9376-3365908cf428 869 | # ╟─5a3e13a9-78a6-46e0-bec5-5fa18b9db13d 870 | # ╠═153453d8-2de0-4a40-86b9-24cf83e2d8ee 871 | # ╠═8ee0c629-8c1e-4d61-b9fe-d2fe3a9543ed 872 | # ╟─bbfe4b6e-8b72-4f6b-b516-1b8838adbcee 873 | # ╟─8f7849aa-6302-4feb-b6c2-a4b27d3d4bd8 874 | # ╠═eb80ec1a-5728-48e0-9836-2270ce4ed87a 875 | # ╟─7b37c063-8142-473f-9d71-0b5edada4e20 876 | # ╠═acd812ce-19f1-42f2-80a0-4b0f4cca006f 877 | # ╟─5f459761-faa9-492e-8fe3-b95634a39c0c 878 | # ╠═64979eaa-e551-4da3-9203-ee75bc5d64d2 879 | # ╠═70ce2499-3b4a-4213-a6de-d3b9454a62fa 880 | # ╟─bf68439d-d1f8-437b-b851-bcfd65ab13ea 881 | # ╟─6405964a-f5e2-471e-a054-adcf0e5db512 882 | # ╠═edd75ea3-84dc-45f7-adec-540b7984aaa9 883 | # ╠═feebcf59-527e-4b49-87f9-0090002e9454 884 | # ╠═9eb49bae-fbf7-49e1-b8aa-3b939d577dee 885 | # ╠═eea1458e-7fa1-4772-9dba-246d3eeeda9c 886 | # ╠═b6a10960-4e3c-4fef-93ed-118dbd3493a7 887 | # ╟─a42329cc-5a69-4ba2-97e0-8e45b7fd9a67 888 | # ╠═095f1ce7-e626-453e-9d7e-cf0af284d7ed 889 | # ╠═ac31e2a8-4c91-44f0-85cb-dc4751fd1c62 890 | # ╠═e803605e-c56e-442e-a60f-707a07dc4009 891 | # ╠═9056fa71-a624-4430-9af6-1c9dbd8df961 892 | # ╠═557eb079-b812-4fc6-b78a-2d933ef80215 893 | # ╟─67b3ec44-f9b8-42d6-828b-bb05007aff27 894 | # ╟─8139e91c-96e3-11eb-1d43-7d9502ac6d91 895 | # ╟─ce083a66-96f5-11eb-1e1c-639e4764cc51 896 | # ╟─c468cc76-97d3-4305-b575-e1aa352ec0ff 897 | # ╟─d661036f-ea13-4e4d-95da-5cfa4786c786 898 | # ╟─e75b1b83-7a97-4b8f-9be0-b72a5d09d713 899 | # ╟─dbc150ba-c617-4ab4-96b2-f6f6d208a47b 900 | # ╟─f5643e42-9504-4ea9-82d5-fa7574da88b1 901 | # ╟─d5f1b957-d9c8-4ad7-aa36-3ff818d69fde 902 | # ╟─daac8a8b-294c-437a-859d-fe8c613e4b39 903 | # ╟─a3bb44ae-f745-4cc9-a983-e019ea35c780 904 | # ╟─7573a640-96e3-11eb-1214-070209074966 905 | -------------------------------------------------------------------------------- /notebooks/topic-6.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.19.9 3 | 4 | using Markdown 5 | using InteractiveUtils 6 | 7 | # ╔═╡ cdb726be-e34c-11eb-17ba-010997657721 8 | md" # Numerical Integration " 9 | 10 | # ╔═╡ Cell order: 11 | # ╟─cdb726be-e34c-11eb-17ba-010997657721 12 | -------------------------------------------------------------------------------- /notebooks/topic-9.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.15.1 3 | 4 | using Markdown 5 | using InteractiveUtils 6 | 7 | # ╔═╡ 786d5fea-e4d0-11eb-027b-614383420965 8 | md" # Dynamic Programming III " 9 | 10 | # ╔═╡ 9c04f013-95d5-46f5-9649-b47a08b9fa4c 11 | md" Here we will go beyond value and policy function iteration and move into time iteration and the endogenous grid method. These methods will be applied directly to the stochastic optimal growth problem and the income fluctuation problem. " 12 | 13 | # ╔═╡ Cell order: 14 | # ╟─786d5fea-e4d0-11eb-027b-614383420965 15 | # ╟─9c04f013-95d5-46f5-9649-b47a08b9fa4c 16 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CompEcon", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": {} 6 | } 7 | -------------------------------------------------------------------------------- /papers/aruoba-fernandez.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DawievLill/CompEconNotes/926dd86c9ec1e7e1f1d39ac894162c60d00110dc/papers/aruoba-fernandez.pdf -------------------------------------------------------------------------------- /papers/coleman-lyon-maliar.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DawievLill/CompEconNotes/926dd86c9ec1e7e1f1d39ac894162c60d00110dc/papers/coleman-lyon-maliar.pdf -------------------------------------------------------------------------------- /scripts/hd_dpp.jl: -------------------------------------------------------------------------------- 1 | 2 | # Julia replication of Solving High-Dimensional Dynamic Programming Problems using Deep Learning 3 | # Original code written for Tensorflow by Jesús Fernández-Villaverde (University of Pennsylvania, NBER and CEPR), Roberto-Rafael Maura-Rivero (London School of Economics), Galo Nuño (Banco de España), George Sorg-Langhans (Princeton University) and Maximilian Vogler (Princeton University) 4 | 5 | # Required packages 6 | using Distributions 7 | using Flux 8 | using LinearAlgebra 9 | using Parameters 10 | using Plots 11 | using Random 12 | using Zygote 13 | 14 | 15 | # Parameter defaults (MWE, so not all included) 16 | @with_kw struct Params 17 | 18 | # Note: type declarations not strictly required (could have impact on speed, but unlikely) 19 | 20 | γ::Float64 = 2.0 # curvature of the utility function 21 | ρ::Float64 = 0.04 # discount rate 22 | A::Float64 = 0.5 # total factor productivity 23 | α::Float64 = 0.36 # returns to scale 24 | δ::Float64 = 0.05 # depreciation rate of capital 25 | 26 | k_min::Float64 = 0.1 27 | k_max::Float64 = 10.0 28 | batch_size::Int64 = 1000 29 | 30 | # ergodic distribution estimation (not used in this setup) 31 | n_burned::Int64 = 1 # number of periods iterated to move away from starting point 32 | 33 | # parameters for neural network 34 | n_neurons::Int64 = 8 35 | input_dim::Int64 = 1 36 | 37 | # misc 38 | dt::Float64 = 0.1 39 | epsilon::Int64 = 1 40 | 41 | end 42 | 43 | p = Params() # change parameter defaults here 44 | 45 | ### MODEL 46 | 47 | # Value function neural net 48 | function neural_net_vf(p::Params; bias = true) 49 | @unpack n_neurons, input_dim = p 50 | 51 | # neural network with three hidden layers 52 | return model = Chain( 53 | Dense(input_dim, n_neurons, tanh), 54 | Dense(n_neurons, n_neurons, tanh), 55 | Dense(n_neurons, n_neurons, tanh), 56 | Dense(n_neurons, 1, bias = -60 * ones(1)) 57 | ) 58 | end 59 | 60 | # Policy function neural net 61 | function neural_net_cf(p::Params; bias = true) 62 | @unpack n_neurons, input_dim = p 63 | 64 | # neural network with three hidden layers 65 | return model = Chain( 66 | Dense(input_dim, n_neurons, tanh), 67 | Dense(n_neurons, n_neurons, tanh), 68 | Dense(n_neurons, n_neurons, tanh), 69 | Dense(n_neurons, 1, bias = zeros(1)) 70 | ) 71 | end 72 | 73 | # This generates 169 parameters, which is the same as the TF code 74 | 75 | #### HJB EQUATION 76 | 77 | # Value error stems from this 78 | function hjb(p::Params, k_capital, V, C) 79 | @unpack A, α, δ, ρ, γ = p 80 | 81 | v_prime = Zygote.gradient(k_capital -> sum(V(k_capital)), k_capital)[1] # Have to take the sum to reflect same as TensorFlow 82 | 83 | Y = A * k_capital .^ α # output 84 | I = Y - exp.(C(k_capital)) # investment 85 | dK_dt = I - δ * k_capital # capital drift (dK/dt) 86 | 87 | # check the explicit functional form from the paper 88 | U = (exp.(C(k_capital)) .^ (1 - γ)) / (1 - γ) # utility 89 | hjb = U - ρ * V(k_capital) + Zygote.dropgrad(v_prime) .* dK_dt 90 | 91 | return hjb 92 | end 93 | 94 | function ergodic_distribution(p::Params, k_capital, C) 95 | @unpack A, α, δ, ρ, n_burned, dt = p 96 | 97 | # iterate points to estimate the ergodic distribution (check the range of the for loop here) 98 | for i in 1:n_burned 99 | 100 | Y = A * k_capital .^ α # output 101 | I = Y - exp.(C(k_capital)) # investment 102 | dK_dt = I - δ * k_capital # capital drift 103 | 104 | k_capital = k_capital + (dt .* dK_dt) 105 | end 106 | return k_capital 107 | end 108 | 109 | # Boundary error option 1 110 | function boundary_condition_ergodic_1_step(p::Params, k_capital, C) 111 | @unpack A, α, δ, dt, k_min, k_max = p 112 | 113 | Y = A * k_capital .^ α # output 114 | I = Y - exp.(C(k_capital)) # investment 115 | dK_dt = I - δ .* k_capital # capital drift (also known as dK/dt) 116 | k_capital_t_plus_one = k_capital + (dt .* dK_dt) 117 | 118 | # we require that k_min < k(t+1) < k_max! 119 | error_lowerbound = max.(k_min .- k_capital_t_plus_one, 0) 120 | error_upperbound = max.(k_capital_t_plus_one .- k_max, 0) 121 | error = error_lowerbound .+ error_upperbound 122 | return error 123 | end 124 | 125 | # Boundary error option 2 126 | function boundary_condition(p::Params, k_capital, C) 127 | @unpack A, α, δ, ρ, n_burned, k_min, epsilon = p 128 | 129 | Y = A * k_capital .^ α # output 130 | I = Y - exp.(C(k_capital)) # investment 131 | dK_dt = I - δ * k_capital # capital drift (also known as dK/dt) 132 | error = ifelse.(k_capital .< epsilon .&& dK_dt .< 0, dK_dt, 0) 133 | 134 | return error 135 | end 136 | 137 | # Consumption error 138 | function c_error(p::Params, k_capital, V, C) 139 | @unpack γ = p 140 | 141 | v_prime = Zygote.gradient(k_capital -> sum(V(k_capital)), k_capital)[1] # dV/dk 142 | v_prime_max = max.(v_prime, 1e-7) 143 | c_err = v_prime_max .^ (-1 ./ γ) - exp.(C(k_capital)) 144 | 145 | return c_err 146 | end 147 | 148 | ### LOSS FUNCTION 149 | 150 | # Set global seed 151 | Random.seed!(42) 152 | 153 | function loss_function(V, C) 154 | 155 | # Training data 156 | k_capital = Flux.flatten(rand(Uniform(0.1, 10.0), 1000)) 157 | 158 | ergodic_k_capital = ergodic_distribution(p, k_capital, C) 159 | 160 | #error_v = hjb(p, ergodic_k_capital, V, C) 161 | #error_c = c_error(p, ergodic_k_capital, V, C) 162 | #error_b = boundary_condition(p, ergodic_k_capital, V, C) 163 | #error_b = boundary_condition_ergodic_1_step(p, ergodic_k_capital, C) 164 | 165 | #loss_v = mean(error_v)^2 # `mean` should do the same as `tf.reduce_mean` and `np.mean` 166 | #loss_c = mean(error_c)^2 167 | #loss_b = mean(error_b)^2 168 | #total_loss = loss_v + loss_c + loss_b 169 | 170 | # The following should result in fewer allocations(?) 171 | loss_v = mean(hjb(p, ergodic_k_capital, V, C))^2 172 | loss_c = mean(c_error(p, ergodic_k_capital, V, C))^2 173 | loss_b = mean(boundary_condition(p, ergodic_k_capital, C))^2 174 | # loss_b = mean(boundary_condition_ergodic_1_step(p, ergodic_k_capital, C))^2 175 | total_loss = loss_v + loss_c + loss_b 176 | 177 | return total_loss 178 | end 179 | 180 | #### TRAIN THE MODEL 181 | 182 | # Set up the neural network 183 | model_vf = neural_net_vf(p) 184 | model_cf = neural_net_cf(p) 185 | 186 | # Choose the appropriate optimizer 187 | opt = ADAM() # can specify η learning rate and decay of momentum β::Tuple here 188 | 189 | # Custom training loop 190 | function custom_train!(loss_function, model_vf, model_cf, opt) 191 | 192 | # Define the trainable network parameters 193 | ps_vf = Flux.params(model_vf) # trainable parameters of model (VF) 194 | ps_cf = Flux.params(model_cf) # trainable parameters of model (CF) 195 | 196 | # This is for the total loss, we calculate the loss and gradient values using the pullback function 197 | total_loss_vf, grads_vf = Zygote.pullback(() -> loss_function(model_vf, model_cf), ps_vf) 198 | total_loss_cf, grads_cf = Zygote.pullback(() -> loss_function(model_vf, model_cf), ps_cf) 199 | 200 | # gradients in correct format for evaluation 201 | grads_v = grads_vf(one(total_loss_vf)) 202 | grads_c = grads_cf(one(total_loss_cf)) 203 | 204 | # updates the parameters (same as optimizer.apply_gradients in TF) via ADAM 205 | Flux.Optimise.update!(opt, ps_vf, grads_v) 206 | Flux.Optimise.update!(opt, ps_cf, grads_c) 207 | end 208 | 209 | #### RUN THE MODEL 210 | 211 | # Function to run model and track losses 212 | function run_model(num_epochs) 213 | 214 | losses = [] 215 | 216 | for i in 1:num_epochs 217 | custom_train!(loss_function, model_vf, model_cf, opt) 218 | push!(losses, loss_function(model_vf, model_cf)) 219 | 220 | println("Epoch = $i") 221 | end 222 | return losses 223 | end 224 | 225 | # Run the model for certain amount of epochs 226 | losses = run_model(10000) 227 | 228 | # Print the results 229 | println("Sum of errors: ", losses[end]) 230 | 231 | #### PLOTTING 232 | plot(losses, xaxis = :log, yaxis = :log) # Log-log scale 233 | 234 | # Capital range 235 | K = LinRange(0.1, 10.0, 1000); 236 | 237 | # Value function plot 238 | plot(K, model_vf(K')') 239 | 240 | # Policy function plot 241 | plot(K, model_cf(K')') -------------------------------------------------------------------------------- /scripts/intro.jl: -------------------------------------------------------------------------------- 1 | using DrWatson 2 | @quickactivate "CompEcon" 3 | DrWatson.greet() 4 | -------------------------------------------------------------------------------- /scripts/iterative.jl: -------------------------------------------------------------------------------- 1 | 2 | # Live coding session 3 | 4 | using LinearAlgebra 5 | 6 | A = I(2) 7 | cond(A) 8 | 9 | ϵ = 1E-6 10 | 11 | A2 = [1.0 0.0 12 | 1.0 ϵ] 13 | 14 | cond(A2) 15 | 16 | inv(A2) 17 | 18 | det(A2) # poor conditioning 19 | 20 | # Gauss-Jacobi, Gauss-Seidel, Conjugate gradient (newest) 21 | 22 | 23 | -------------------------------------------------------------------------------- /scripts/jump-example.jl: -------------------------------------------------------------------------------- 1 | 2 | # Simple example using JuMP 3 | 4 | using JuMP 5 | using GLPK 6 | 7 | model = Model(with_optimizer(GLPK.Optimizer)) # Specify the optimizer 8 | @variable(model, 0 <= x <= 2) # Provide range for x variable 9 | @variable(model, 0 <= y <= 30) # Provide range for y variable 10 | 11 | # next, we set an objective function 12 | @objective(model, Max, 5x + 3y) 13 | 14 | # maybe add a constraint called "con"? 15 | @constraint(model, con, 1x + 5y <= 3) 16 | 17 | JuMP.optimize!(model) 18 | 19 | # look at status 20 | termination_status(model) 21 | 22 | # we query objective value and solutions 23 | @show objective_value(model) 24 | @show value(x) 25 | @show value(y) 26 | 27 | # as well as the value of the dual variable on the constraint (Lagrange multiplier) 28 | @show dual(con); 29 | -------------------------------------------------------------------------------- /scripts/jump-rosenbrock.jl: -------------------------------------------------------------------------------- 1 | 2 | 3 | # JuMP: nonlinear Rosenbrock Example 4 | # Instead of hand-coding first and second derivatives, you only have to give `JuMP` expressions for objective and constraints. 5 | # Here is an example. 6 | 7 | using JuMP 8 | using Ipopt 9 | 10 | let 11 | 12 | m₁ = Model(with_optimizer(Ipopt.Optimizer)) 13 | 14 | @variable(m₁, x₁) 15 | @variable(m₁, y₁) 16 | 17 | @NLobjective(m₁, Min, (1-x₁)^2 + 100(y₁-x₁^2)^2) 18 | 19 | JuMP.optimize!(m₁) 20 | @show value(x₁) 21 | @show value(y₁) 22 | @show termination_status(m₁) 23 | 24 | end 25 | 26 | # not bad, right? 27 | # adding the constraint from before: 28 | 29 | let 30 | 31 | m₂ = Model(with_optimizer(Ipopt.Optimizer)) 32 | 33 | @variable(m₂, x₂) 34 | @variable(m₂, y₂) 35 | 36 | @NLobjective(m₂, Min, (1-x₂)^2 + 100(y₂-x₂^2)^2) 37 | 38 | 39 | @NLconstraint(m₂, con, x₂^2 + y₂^2 <= 0.8) 40 | 41 | JuMP.optimize!(m₂) 42 | @show value(x₂) 43 | @show value(y₂) 44 | @show termination_status(m₂) 45 | @show dual(con) 46 | 47 | end -------------------------------------------------------------------------------- /scripts/rjulia.jl: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Quick script to show some of the functionality of RCall. We could do something similar with Python, Matlab and C++. Julia has packages that interact with all these languages (and more). 4 | 5 | using RCall 6 | using Gadfly 7 | 8 | # This initial portion is all R code that is called by Julia 9 | 10 | R""" 11 | library(ggplot2) 12 | library(dplyr) 13 | 14 | df <- ToothGrowth %>% 15 | group_by(supp, dose) %>% 16 | summarise(se = sd(len) / n(), len = mean(len), n = n()) 17 | 18 | ggplot(df, aes(x = dose, y = len, group = supp, color = supp)) + 19 | geom_line() + 20 | geom_point() + 21 | geom_errorbar(aes(ymin = len - se, ymax = len + se), width = 0.1, alpha = 0.5, 22 | position = position_dodge(0.005)) + 23 | scale_color_manual(values = c(VC = "skyblue", OJ = "orange")) + 24 | labs(x = "Dose", y = "Tooth Length") 25 | """ 26 | 27 | # Retrieve dataframe from R to Julia workspace 28 | 29 | @rget df 30 | 31 | 32 | # Use Julia commands on the dataframe as retrieved from R. 33 | df[:ymin] = df[:len] - df[:se] 34 | df[:ymax] = df[:len] + df[:se] 35 | Gadfly.plot(df, 36 | x = :dose, 37 | y = :len, 38 | color = :supp, 39 | Geom.point, 40 | Guide.xlabel("Dose"), 41 | Guide.ylabel("Tooth Length"), 42 | Guide.xticks(ticks = [0.5, 1.0, 1.5, 2.0]), 43 | Geom.line, 44 | Geom.errorbar, 45 | ymin = :ymin, 46 | ymax = :ymax, 47 | Scale.color_discrete_manual("orange", "skyblue")) 48 | 49 | 50 | --------------------------------------------------------------------------------