├── .gitignore
├── _notebook_repo
├── .gitignore
└── README.md
├── lectures
├── _static
│ ├── banner.png
│ ├── pdfs
│ │ ├── pi2.pdf
│ │ ├── 3ndp.pdf
│ │ ├── ECTA6180.pdf
│ │ ├── firenze.pdf
│ │ ├── aiyagari_obit.pdf
│ │ ├── course_notes.pdf
│ │ ├── new-branch-10.png
│ │ ├── iteration_notes.pdf
│ │ └── time_series_book.pdf
│ ├── figures
│ │ ├── kg.png
│ │ ├── kg0.png
│ │ ├── tsh.png
│ │ ├── ci_1.png
│ │ ├── ci_2.png
│ │ ├── ci_3.png
│ │ ├── ci_4.png
│ │ ├── ci_5.png
│ │ ├── ci_6.png
│ │ ├── ci_7.png
│ │ ├── ci_8.png
│ │ ├── graph.png
│ │ ├── tsh0.png
│ │ ├── ci_5_1.png
│ │ ├── ci_6_2.png
│ │ ├── ci_6_3.png
│ │ ├── ci_7_2.png
│ │ ├── git-pull.png
│ │ ├── graph2.png
│ │ ├── graph3.png
│ │ ├── graph4.png
│ │ ├── repl_1.png
│ │ ├── repl_2.png
│ │ ├── tsh_hg.png
│ │ ├── codecov_1.png
│ │ ├── codecov_2.png
│ │ ├── codecov_3.png
│ │ ├── codecov_4.png
│ │ ├── codecov_5.png
│ │ ├── codecov_6.png
│ │ ├── codecov_7.png
│ │ ├── codecov_8.png
│ │ ├── debugger_1.png
│ │ ├── debugger_2.png
│ │ ├── git-branch.png
│ │ ├── git-clone.png
│ │ ├── git-collab.png
│ │ ├── git-issue.png
│ │ ├── git-review.png
│ │ ├── judd_fig1.png
│ │ ├── judd_fig2.png
│ │ ├── julia-path.png
│ │ ├── juno-docs.png
│ │ ├── juno-plots.png
│ │ ├── kalman_ex3.png
│ │ ├── kl_ex1_fig.png
│ │ ├── kl_ex2_fig.png
│ │ ├── nb2_julia.png
│ │ ├── nb3_julia.png
│ │ ├── nb4_julia.png
│ │ ├── nb5_julia.png
│ │ ├── nb6_julia.png
│ │ ├── nb7_julia.png
│ │ ├── new-branch.png
│ │ ├── travis-log.png
│ │ ├── vfi_vs_pfi.png
│ │ ├── web_graph.png
│ │ ├── col_pol_bij1.png
│ │ ├── col_pol_bij2.png
│ │ ├── ensemble_mean.png
│ │ ├── git-add-local.png
│ │ ├── git-create-pr.png
│ │ ├── git-dropdown.png
│ │ ├── git-edit-fork.png
│ │ ├── git-issue-tab.png
│ │ ├── git-makerepo.png
│ │ ├── git-pr-branch.png
│ │ ├── git-pr-edits.png
│ │ ├── git-pr-expost.png
│ │ ├── git-quick-pr.png
│ │ ├── git-repo-list.png
│ │ ├── git-review-2.png
│ │ ├── git-settings.png
│ │ ├── ifp_histogram.png
│ │ ├── ifp_policies.png
│ │ ├── julia_term_1.png
│ │ ├── lae_marginals.png
│ │ ├── matsuyama_14.png
│ │ ├── mc_ex1_plot.png
│ │ ├── mccall_resw_c.png
│ │ ├── new-branch-10.png
│ │ ├── new-branch-11.png
│ │ ├── new-branch-2.png
│ │ ├── new-branch-3.png
│ │ ├── new-branch-4.png
│ │ ├── new-branch-5.png
│ │ ├── new-branch-6.png
│ │ ├── new-branch-7.png
│ │ ├── new-branch-8.png
│ │ ├── new-branch-9.png
│ │ ├── periodogram1.png
│ │ ├── repeatexample.png
│ │ ├── testing-dir.png
│ │ ├── testing-fork.png
│ │ ├── testing-git1.png
│ │ ├── testing-git2.png
│ │ ├── testing-pr2.png
│ │ ├── vs-code-clone.png
│ │ ├── vscode_plots.png
│ │ ├── vscode_repl_1.png
│ │ ├── wald_dec_rule.png
│ │ ├── git-clone-fork.png
│ │ ├── git-create-pr-2.png
│ │ ├── git-fork-button.png
│ │ ├── git-lfs-dialog.png
│ │ ├── git-new-branch.png
│ │ ├── hamilton_graph.png
│ │ ├── ifp_agg_savings.png
│ │ ├── kg_small_theta.png
│ │ ├── orth_proj_def1.png
│ │ ├── orth_proj_def2.png
│ │ ├── orth_proj_def3.png
│ │ ├── orth_proj_thm1.png
│ │ ├── orth_proj_thm2.png
│ │ ├── orth_proj_thm3.png
│ │ ├── schelling_fig1.png
│ │ ├── schelling_fig2.png
│ │ ├── schelling_fig3.png
│ │ ├── schelling_fig4.png
│ │ ├── solution_og_ex2.png
│ │ ├── test_program_1.png
│ │ ├── testing-commit.png
│ │ ├── testing-output.png
│ │ ├── travis-progress.png
│ │ ├── travis-settings.png
│ │ ├── travis-trigger.png
│ │ ├── vs-code-edits-1.png
│ │ ├── vs-code-edits-2.png
│ │ ├── vs-code-edits-3.png
│ │ ├── vs-code-edits-4.png
│ │ ├── vs-code-edits-5.png
│ │ ├── vs-code-edits-6.png
│ │ ├── vs-code-edits-7.png
│ │ ├── vs-code-edits-8.png
│ │ ├── vs-code-edits-9.png
│ │ ├── vscode_intro_0.png
│ │ ├── vscode_intro_1.png
│ │ ├── vscode_intro_2.png
│ │ ├── vscode_intro_3.png
│ │ ├── vscode_intro_4.png
│ │ ├── vscode_intro_5.png
│ │ ├── vscode_intro_6.png
│ │ ├── vscode_intro_7.png
│ │ ├── vscode_latex_1.png
│ │ ├── vscode_latex_2.png
│ │ ├── docker-hello-world.png
│ │ ├── docker-jlab-full.png
│ │ ├── docker-jupyter-lab.png
│ │ ├── git-desktop-commit.png
│ │ ├── git-desktop-intro.png
│ │ ├── git-fork-changes.png
│ │ ├── git-fork-history.png
│ │ ├── git-makerepo-full.png
│ │ ├── git-merge-commit.png
│ │ ├── git-merge-conflict.png
│ │ ├── git-revert-commit.png
│ │ ├── julia_formatter_1.png
│ │ ├── julia_formatter_2.png
│ │ ├── juno-workspace-1.png
│ │ ├── jupyterlab_first.png
│ │ ├── mc_aperiodicity1.png
│ │ ├── mc_aperiodicity2.png
│ │ ├── mc_irreducibility1.png
│ │ ├── mc_irreducibility2.png
│ │ ├── mccall_resw_alpha.png
│ │ ├── mccall_resw_beta.png
│ │ ├── mpe_vs_monopolist.png
│ │ ├── new_package_vscode.png
│ │ ├── sine-screenshot-2.png
│ │ ├── solution_lqc_ex1.png
│ │ ├── solution_lqc_ex2.png
│ │ ├── solution_lss_ex1.png
│ │ ├── solution_lss_ex2.png
│ │ ├── solution_mass_ex2.png
│ │ ├── solution_statd_ex1.png
│ │ ├── solution_statd_ex2.png
│ │ ├── starting_nb_julia.png
│ │ ├── testing-notebook.png
│ │ ├── vs-code-done-clone.png
│ │ ├── vs-code-edits-10.png
│ │ ├── vs-code-edits-11.png
│ │ ├── vs-code-edits-12.png
│ │ ├── vs-code-edits-13.png
│ │ ├── vs-code-edits-14.png
│ │ ├── vs-code-edits-15.png
│ │ ├── vs-code-edits-16.png
│ │ ├── vscode_add_package.png
│ │ ├── vscode_jl_function.png
│ │ ├── vscode_jupyter_1.png
│ │ ├── vscode_jupyter_2.png
│ │ ├── vscode_jupyter_3.png
│ │ ├── window_smoothing.png
│ │ ├── arellano_bond_prices.png
│ │ ├── arellano_time_series.png
│ │ ├── arellano_value_funcs.png
│ │ ├── atom-merge-conflict.png
│ │ ├── col_pol_composition.png
│ │ ├── docker-basic-command.png
│ │ ├── finite_dp_simple_og.png
│ │ ├── git-desktop-commit2.png
│ │ ├── git-pr-modification.png
│ │ ├── juno-standard-layout.png
│ │ ├── new_package_vscode_2.png
│ │ ├── new_package_vscode_3.png
│ │ ├── new_package_vscode_4.png
│ │ ├── solution_lqc_ex3_g1.png
│ │ ├── solution_lqc_ex3_g10.png
│ │ ├── solution_lqc_ex3_g50.png
│ │ ├── testing-atom-package.png
│ │ ├── testing-expectations.png
│ │ ├── uncertainty_traps_45.png
│ │ ├── uncertainty_traps_mu.png
│ │ ├── vscode_add_package_2.png
│ │ ├── vscode_file_created.png
│ │ ├── vscode_jl_function_2.png
│ │ ├── vscode_julia_kernel.png
│ │ ├── vscode_package_added.png
│ │ ├── vscode_run_package_1.png
│ │ ├── vscode_run_package_2.png
│ │ ├── vscode_run_package_3.png
│ │ ├── vscode_run_package_4.png
│ │ ├── vscode_run_package_5.png
│ │ ├── vscode_run_package_6.png
│ │ ├── ar_smoothed_periodogram.png
│ │ ├── arellano_bond_prices_2.png
│ │ ├── arellano_default_probs.png
│ │ ├── career_solutions_ex1_jl.png
│ │ ├── career_solutions_ex3_jl.png
│ │ ├── covariance_stationary.png
│ │ ├── lake_distribution_wages.png
│ │ ├── new_package_vscode_4_2.png
│ │ ├── new_package_vscode_4_3.png
│ │ ├── paths_and_stationarity.png
│ │ ├── testing-atom-manifest.png
│ │ ├── testing-repo-settings.png
│ │ ├── uncertainty_traps_sim.png
│ │ ├── docker-packages-preinstalled.png
│ │ └── vscode_jupyter_kernel_execute.png
│ ├── qe-logo-large.png
│ ├── lectures-favicon.ico
│ ├── quantecon-logo-transparent.png
│ ├── code
│ │ ├── julia_essentials
│ │ │ └── us_cities.txt
│ │ └── linear_models
│ │ │ └── paths_and_hist.jl
│ └── includes
│ │ └── header.raw
├── getting_started_julia
│ └── us_cities.txt
├── zreferences.md
├── intro.md
├── status.md
├── Project.toml
├── troubleshooting.md
├── _toc.yml
├── _config.yml
├── tools_and_techniques
│ └── differentiable_simulation.jl
├── more_julia
│ └── data_statistical_packages.md
├── multi_agent_models
│ ├── schelling.md
│ └── aiyagari.md
├── about_lectures.md
└── introduction_dynamics
│ ├── scalar_dynam.md
│ └── short_path.md
├── .JuliaFormatter.toml
├── requirements.txt
├── .github
├── dependabot.yml
├── workflows
│ ├── format.yml
│ ├── cache.yml
│ ├── ci.yml
│ └── publish.yml
└── copilot-instructions.md
├── format_all_directory.sh
├── prompts
├── enzyme_test.jl
├── simulation_prompt.md
└── differentiation.md
├── format_myst.jl
├── wsl.md
├── AGENTS.md
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | _build
2 | us_cities.txt
3 | .DS_Store
4 | .vscode
5 |
--------------------------------------------------------------------------------
/_notebook_repo/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | **/.ipynb_checkpoints
3 | .vscode/settings.json
--------------------------------------------------------------------------------
/lectures/_static/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/banner.png
--------------------------------------------------------------------------------
/lectures/_static/pdfs/pi2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/pdfs/pi2.pdf
--------------------------------------------------------------------------------
/.JuliaFormatter.toml:
--------------------------------------------------------------------------------
1 | style = "sciml"
2 | margin = 80
3 | yas_style_nesting = true
4 | annotate_untyped_fields_with_any = false
--------------------------------------------------------------------------------
/lectures/_static/figures/kg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/kg.png
--------------------------------------------------------------------------------
/lectures/_static/figures/kg0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/kg0.png
--------------------------------------------------------------------------------
/lectures/_static/figures/tsh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/tsh.png
--------------------------------------------------------------------------------
/lectures/_static/pdfs/3ndp.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/pdfs/3ndp.pdf
--------------------------------------------------------------------------------
/lectures/_static/figures/ci_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ci_1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ci_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ci_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ci_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ci_3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ci_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ci_4.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ci_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ci_5.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ci_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ci_6.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ci_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ci_7.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ci_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ci_8.png
--------------------------------------------------------------------------------
/lectures/_static/figures/graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/graph.png
--------------------------------------------------------------------------------
/lectures/_static/figures/tsh0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/tsh0.png
--------------------------------------------------------------------------------
/lectures/_static/pdfs/ECTA6180.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/pdfs/ECTA6180.pdf
--------------------------------------------------------------------------------
/lectures/_static/pdfs/firenze.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/pdfs/firenze.pdf
--------------------------------------------------------------------------------
/lectures/_static/qe-logo-large.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/qe-logo-large.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ci_5_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ci_5_1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ci_6_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ci_6_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ci_6_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ci_6_3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ci_7_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ci_7_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-pull.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-pull.png
--------------------------------------------------------------------------------
/lectures/_static/figures/graph2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/graph2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/graph3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/graph3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/graph4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/graph4.png
--------------------------------------------------------------------------------
/lectures/_static/figures/repl_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/repl_1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/repl_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/repl_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/tsh_hg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/tsh_hg.png
--------------------------------------------------------------------------------
/lectures/_static/lectures-favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/lectures-favicon.ico
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | jupyter-book==0.15.1
2 | quantecon-book-theme==0.7.1
3 | sphinx-tojupyter==0.3.0
4 | sphinxext.rediraffe==0.2.7
5 | pip
--------------------------------------------------------------------------------
/lectures/_static/figures/codecov_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/codecov_1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/codecov_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/codecov_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/codecov_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/codecov_3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/codecov_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/codecov_4.png
--------------------------------------------------------------------------------
/lectures/_static/figures/codecov_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/codecov_5.png
--------------------------------------------------------------------------------
/lectures/_static/figures/codecov_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/codecov_6.png
--------------------------------------------------------------------------------
/lectures/_static/figures/codecov_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/codecov_7.png
--------------------------------------------------------------------------------
/lectures/_static/figures/codecov_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/codecov_8.png
--------------------------------------------------------------------------------
/lectures/_static/figures/debugger_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/debugger_1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/debugger_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/debugger_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-branch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-branch.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-clone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-clone.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-collab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-collab.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-issue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-issue.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-review.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-review.png
--------------------------------------------------------------------------------
/lectures/_static/figures/judd_fig1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/judd_fig1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/judd_fig2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/judd_fig2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/julia-path.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/julia-path.png
--------------------------------------------------------------------------------
/lectures/_static/figures/juno-docs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/juno-docs.png
--------------------------------------------------------------------------------
/lectures/_static/figures/juno-plots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/juno-plots.png
--------------------------------------------------------------------------------
/lectures/_static/figures/kalman_ex3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/kalman_ex3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/kl_ex1_fig.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/kl_ex1_fig.png
--------------------------------------------------------------------------------
/lectures/_static/figures/kl_ex2_fig.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/kl_ex2_fig.png
--------------------------------------------------------------------------------
/lectures/_static/figures/nb2_julia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/nb2_julia.png
--------------------------------------------------------------------------------
/lectures/_static/figures/nb3_julia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/nb3_julia.png
--------------------------------------------------------------------------------
/lectures/_static/figures/nb4_julia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/nb4_julia.png
--------------------------------------------------------------------------------
/lectures/_static/figures/nb5_julia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/nb5_julia.png
--------------------------------------------------------------------------------
/lectures/_static/figures/nb6_julia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/nb6_julia.png
--------------------------------------------------------------------------------
/lectures/_static/figures/nb7_julia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/nb7_julia.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new-branch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new-branch.png
--------------------------------------------------------------------------------
/lectures/_static/figures/travis-log.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/travis-log.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vfi_vs_pfi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vfi_vs_pfi.png
--------------------------------------------------------------------------------
/lectures/_static/figures/web_graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/web_graph.png
--------------------------------------------------------------------------------
/lectures/_static/pdfs/aiyagari_obit.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/pdfs/aiyagari_obit.pdf
--------------------------------------------------------------------------------
/lectures/_static/pdfs/course_notes.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/pdfs/course_notes.pdf
--------------------------------------------------------------------------------
/lectures/_static/pdfs/new-branch-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/pdfs/new-branch-10.png
--------------------------------------------------------------------------------
/lectures/_static/figures/col_pol_bij1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/col_pol_bij1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/col_pol_bij2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/col_pol_bij2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ensemble_mean.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ensemble_mean.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-add-local.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-add-local.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-create-pr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-create-pr.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-dropdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-dropdown.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-edit-fork.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-edit-fork.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-issue-tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-issue-tab.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-makerepo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-makerepo.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-pr-branch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-pr-branch.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-pr-edits.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-pr-edits.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-pr-expost.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-pr-expost.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-quick-pr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-quick-pr.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-repo-list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-repo-list.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-review-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-review-2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-settings.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ifp_histogram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ifp_histogram.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ifp_policies.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ifp_policies.png
--------------------------------------------------------------------------------
/lectures/_static/figures/julia_term_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/julia_term_1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/lae_marginals.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/lae_marginals.png
--------------------------------------------------------------------------------
/lectures/_static/figures/matsuyama_14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/matsuyama_14.png
--------------------------------------------------------------------------------
/lectures/_static/figures/mc_ex1_plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/mc_ex1_plot.png
--------------------------------------------------------------------------------
/lectures/_static/figures/mccall_resw_c.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/mccall_resw_c.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new-branch-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new-branch-10.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new-branch-11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new-branch-11.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new-branch-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new-branch-2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new-branch-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new-branch-3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new-branch-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new-branch-4.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new-branch-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new-branch-5.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new-branch-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new-branch-6.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new-branch-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new-branch-7.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new-branch-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new-branch-8.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new-branch-9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new-branch-9.png
--------------------------------------------------------------------------------
/lectures/_static/figures/periodogram1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/periodogram1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/repeatexample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/repeatexample.png
--------------------------------------------------------------------------------
/lectures/_static/figures/testing-dir.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/testing-dir.png
--------------------------------------------------------------------------------
/lectures/_static/figures/testing-fork.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/testing-fork.png
--------------------------------------------------------------------------------
/lectures/_static/figures/testing-git1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/testing-git1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/testing-git2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/testing-git2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/testing-pr2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/testing-pr2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-clone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-clone.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_plots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_plots.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_repl_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_repl_1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/wald_dec_rule.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/wald_dec_rule.png
--------------------------------------------------------------------------------
/lectures/_static/pdfs/iteration_notes.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/pdfs/iteration_notes.pdf
--------------------------------------------------------------------------------
/lectures/_static/pdfs/time_series_book.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/pdfs/time_series_book.pdf
--------------------------------------------------------------------------------
/lectures/_static/figures/git-clone-fork.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-clone-fork.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-create-pr-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-create-pr-2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-fork-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-fork-button.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-lfs-dialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-lfs-dialog.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-new-branch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-new-branch.png
--------------------------------------------------------------------------------
/lectures/_static/figures/hamilton_graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/hamilton_graph.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ifp_agg_savings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ifp_agg_savings.png
--------------------------------------------------------------------------------
/lectures/_static/figures/kg_small_theta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/kg_small_theta.png
--------------------------------------------------------------------------------
/lectures/_static/figures/orth_proj_def1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/orth_proj_def1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/orth_proj_def2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/orth_proj_def2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/orth_proj_def3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/orth_proj_def3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/orth_proj_thm1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/orth_proj_thm1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/orth_proj_thm2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/orth_proj_thm2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/orth_proj_thm3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/orth_proj_thm3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/schelling_fig1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/schelling_fig1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/schelling_fig2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/schelling_fig2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/schelling_fig3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/schelling_fig3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/schelling_fig4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/schelling_fig4.png
--------------------------------------------------------------------------------
/lectures/_static/figures/solution_og_ex2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/solution_og_ex2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/test_program_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/test_program_1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/testing-commit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/testing-commit.png
--------------------------------------------------------------------------------
/lectures/_static/figures/testing-output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/testing-output.png
--------------------------------------------------------------------------------
/lectures/_static/figures/travis-progress.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/travis-progress.png
--------------------------------------------------------------------------------
/lectures/_static/figures/travis-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/travis-settings.png
--------------------------------------------------------------------------------
/lectures/_static/figures/travis-trigger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/travis-trigger.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-4.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-5.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-6.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-7.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-8.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-9.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_intro_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_intro_0.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_intro_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_intro_1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_intro_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_intro_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_intro_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_intro_3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_intro_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_intro_4.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_intro_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_intro_5.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_intro_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_intro_6.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_intro_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_intro_7.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_latex_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_latex_1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_latex_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_latex_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/docker-hello-world.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/docker-hello-world.png
--------------------------------------------------------------------------------
/lectures/_static/figures/docker-jlab-full.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/docker-jlab-full.png
--------------------------------------------------------------------------------
/lectures/_static/figures/docker-jupyter-lab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/docker-jupyter-lab.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-desktop-commit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-desktop-commit.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-desktop-intro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-desktop-intro.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-fork-changes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-fork-changes.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-fork-history.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-fork-history.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-makerepo-full.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-makerepo-full.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-merge-commit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-merge-commit.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-merge-conflict.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-merge-conflict.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-revert-commit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-revert-commit.png
--------------------------------------------------------------------------------
/lectures/_static/figures/julia_formatter_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/julia_formatter_1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/julia_formatter_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/julia_formatter_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/juno-workspace-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/juno-workspace-1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/jupyterlab_first.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/jupyterlab_first.png
--------------------------------------------------------------------------------
/lectures/_static/figures/mc_aperiodicity1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/mc_aperiodicity1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/mc_aperiodicity2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/mc_aperiodicity2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/mc_irreducibility1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/mc_irreducibility1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/mc_irreducibility2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/mc_irreducibility2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/mccall_resw_alpha.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/mccall_resw_alpha.png
--------------------------------------------------------------------------------
/lectures/_static/figures/mccall_resw_beta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/mccall_resw_beta.png
--------------------------------------------------------------------------------
/lectures/_static/figures/mpe_vs_monopolist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/mpe_vs_monopolist.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new_package_vscode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new_package_vscode.png
--------------------------------------------------------------------------------
/lectures/_static/figures/sine-screenshot-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/sine-screenshot-2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/solution_lqc_ex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/solution_lqc_ex1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/solution_lqc_ex2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/solution_lqc_ex2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/solution_lss_ex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/solution_lss_ex1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/solution_lss_ex2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/solution_lss_ex2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/solution_mass_ex2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/solution_mass_ex2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/solution_statd_ex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/solution_statd_ex1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/solution_statd_ex2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/solution_statd_ex2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/starting_nb_julia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/starting_nb_julia.png
--------------------------------------------------------------------------------
/lectures/_static/figures/testing-notebook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/testing-notebook.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-done-clone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-done-clone.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-10.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-11.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-12.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-13.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-14.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-15.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vs-code-edits-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vs-code-edits-16.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_add_package.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_add_package.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_jl_function.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_jl_function.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_jupyter_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_jupyter_1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_jupyter_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_jupyter_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_jupyter_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_jupyter_3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/window_smoothing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/window_smoothing.png
--------------------------------------------------------------------------------
/lectures/_static/quantecon-logo-transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/quantecon-logo-transparent.png
--------------------------------------------------------------------------------
/lectures/_static/figures/arellano_bond_prices.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/arellano_bond_prices.png
--------------------------------------------------------------------------------
/lectures/_static/figures/arellano_time_series.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/arellano_time_series.png
--------------------------------------------------------------------------------
/lectures/_static/figures/arellano_value_funcs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/arellano_value_funcs.png
--------------------------------------------------------------------------------
/lectures/_static/figures/atom-merge-conflict.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/atom-merge-conflict.png
--------------------------------------------------------------------------------
/lectures/_static/figures/col_pol_composition.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/col_pol_composition.png
--------------------------------------------------------------------------------
/lectures/_static/figures/docker-basic-command.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/docker-basic-command.png
--------------------------------------------------------------------------------
/lectures/_static/figures/finite_dp_simple_og.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/finite_dp_simple_og.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-desktop-commit2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-desktop-commit2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/git-pr-modification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/git-pr-modification.png
--------------------------------------------------------------------------------
/lectures/_static/figures/juno-standard-layout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/juno-standard-layout.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new_package_vscode_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new_package_vscode_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new_package_vscode_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new_package_vscode_3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new_package_vscode_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new_package_vscode_4.png
--------------------------------------------------------------------------------
/lectures/_static/figures/solution_lqc_ex3_g1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/solution_lqc_ex3_g1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/solution_lqc_ex3_g10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/solution_lqc_ex3_g10.png
--------------------------------------------------------------------------------
/lectures/_static/figures/solution_lqc_ex3_g50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/solution_lqc_ex3_g50.png
--------------------------------------------------------------------------------
/lectures/_static/figures/testing-atom-package.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/testing-atom-package.png
--------------------------------------------------------------------------------
/lectures/_static/figures/testing-expectations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/testing-expectations.png
--------------------------------------------------------------------------------
/lectures/_static/figures/uncertainty_traps_45.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/uncertainty_traps_45.png
--------------------------------------------------------------------------------
/lectures/_static/figures/uncertainty_traps_mu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/uncertainty_traps_mu.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_add_package_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_add_package_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_file_created.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_file_created.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_jl_function_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_jl_function_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_julia_kernel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_julia_kernel.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_package_added.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_package_added.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_run_package_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_run_package_1.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_run_package_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_run_package_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_run_package_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_run_package_3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_run_package_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_run_package_4.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_run_package_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_run_package_5.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_run_package_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_run_package_6.png
--------------------------------------------------------------------------------
/lectures/_static/figures/ar_smoothed_periodogram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/ar_smoothed_periodogram.png
--------------------------------------------------------------------------------
/lectures/_static/figures/arellano_bond_prices_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/arellano_bond_prices_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/arellano_default_probs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/arellano_default_probs.png
--------------------------------------------------------------------------------
/lectures/_static/figures/career_solutions_ex1_jl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/career_solutions_ex1_jl.png
--------------------------------------------------------------------------------
/lectures/_static/figures/career_solutions_ex3_jl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/career_solutions_ex3_jl.png
--------------------------------------------------------------------------------
/lectures/_static/figures/covariance_stationary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/covariance_stationary.png
--------------------------------------------------------------------------------
/lectures/_static/figures/lake_distribution_wages.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/lake_distribution_wages.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new_package_vscode_4_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new_package_vscode_4_2.png
--------------------------------------------------------------------------------
/lectures/_static/figures/new_package_vscode_4_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/new_package_vscode_4_3.png
--------------------------------------------------------------------------------
/lectures/_static/figures/paths_and_stationarity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/paths_and_stationarity.png
--------------------------------------------------------------------------------
/lectures/_static/figures/testing-atom-manifest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/testing-atom-manifest.png
--------------------------------------------------------------------------------
/lectures/_static/figures/testing-repo-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/testing-repo-settings.png
--------------------------------------------------------------------------------
/lectures/_static/figures/uncertainty_traps_sim.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/uncertainty_traps_sim.png
--------------------------------------------------------------------------------
/lectures/_static/figures/docker-packages-preinstalled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/docker-packages-preinstalled.png
--------------------------------------------------------------------------------
/lectures/_static/figures/vscode_jupyter_kernel_execute.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantEcon/lecture-julia.myst/main/lectures/_static/figures/vscode_jupyter_kernel_execute.png
--------------------------------------------------------------------------------
/lectures/getting_started_julia/us_cities.txt:
--------------------------------------------------------------------------------
1 | new york: 8244910
2 | los angeles: 3819702
3 | chicago: 2707120
4 | houston: 2145146
5 | philadelphia: 1536471
6 | phoenix: 1469471
7 | san antonio: 1359758
8 | san diego: 1326179
9 | dallas: 1223229
--------------------------------------------------------------------------------
/lectures/_static/code/julia_essentials/us_cities.txt:
--------------------------------------------------------------------------------
1 | new york: 8244910
2 | los angeles: 3819702
3 | chicago: 2707120
4 | houston: 2145146
5 | philadelphia: 1536471
6 | phoenix: 1469471
7 | san antonio: 1359758
8 | san diego: 1326179
9 | dallas: 1223229
10 |
--------------------------------------------------------------------------------
/lectures/_static/includes/header.raw:
--------------------------------------------------------------------------------
1 | .. raw:: html
2 |
3 |
8 |
--------------------------------------------------------------------------------
/lectures/zreferences.md:
--------------------------------------------------------------------------------
1 | ---
2 | jupytext:
3 | text_representation:
4 | extension: .md
5 | format_name: myst
6 | kernelspec:
7 | display_name: Julia
8 | language: julia
9 | name: julia-1.12
10 | ---
11 |
12 | (references)=
13 | # References
14 |
15 | ```{bibliography} _static/quant-econ.bib
16 | ```
17 |
18 |
--------------------------------------------------------------------------------
/lectures/intro.md:
--------------------------------------------------------------------------------
1 | ---
2 | jupytext:
3 | text_representation:
4 | extension: .md
5 | format_name: myst
6 | kernelspec:
7 | display_name: Python 3
8 | language: python
9 | name: python3
10 | ---
11 |
12 | # Quantitative Economics with Julia
13 |
14 | This website presents a set of lectures on quantitative economic modeling.
15 |
16 | ```{tableofcontents}
17 | ```
--------------------------------------------------------------------------------
/_notebook_repo/README.md:
--------------------------------------------------------------------------------
1 | # lecture-julia.notebooks
2 |
3 | [](https://mybinder.org/v2/gh/QuantEcon/lecture-julia.notebooks/main)
4 |
5 | Notebooks for https://julia.quantecon.org
6 |
7 | - [Lecture source](https://github.com/QuantEcon/lecture-julia.myst)
8 | - [README source code](https://github.com/QuantEcon/lecture-julia.myst/blob/main/_notebook_repo/README.md)
9 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: github-actions
9 | directory: /
10 | commit-message:
11 | prefix: ⬆️
12 | schedule:
13 | interval: weekly
14 |
--------------------------------------------------------------------------------
/lectures/status.md:
--------------------------------------------------------------------------------
1 | ---
2 | jupytext:
3 | text_representation:
4 | extension: .md
5 | format_name: myst
6 | kernelspec:
7 | display_name: Julia
8 | language: julia
9 | name: julia-1.12
10 | ---
11 |
12 | # Execution Statistics
13 |
14 | This table contains the latest execution statistics.
15 |
16 | ```{nb-exec-table}
17 | ```
18 |
19 | These lectures are built on `linux` instances through `github actions` so are
20 | executed using the following [hardware specifications](https://docs.github.com/en/actions/reference/specifications-for-github-hosted-runners#supported-runners-and-hardware-resources)
--------------------------------------------------------------------------------
/format_all_directory.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Check if at least one argument is given
4 | if [ "$#" -lt 1 ]; then
5 | echo "Usage: $0 path/to/md/files/ [use_replacements]"
6 | exit 1
7 | fi
8 |
9 | # Directory containing markdown files, ensuring it has a trailing slash
10 | dir_path="${1%/}/"
11 |
12 | # Optional use_replacements flag, default to "false" if not provided
13 | use_replacements=${2:-false}
14 |
15 | # Loop over all .md files in the given directory
16 | for file_path in ${dir_path}*.md; do
17 | # Only process regular files
18 | if [ -f "$file_path" ]; then
19 | # Call the Julia script with the current .md file and the use_replacements flag
20 | julia format_myst.jl "$file_path" $use_replacements
21 | fi
22 | done
23 |
--------------------------------------------------------------------------------
/lectures/_static/code/linear_models/paths_and_hist.jl:
--------------------------------------------------------------------------------
1 | using Plots
2 | gr(fmt=:png);
3 | using QuantEcon
4 |
5 | phi_1, phi_2, phi_3, phi_4 = 0.5, -0.2, 0, 0.5
6 | sigma = 0.1
7 |
8 | A = [phi_1 phi_2 phi_3 phi_4
9 | 1.0 0.0 0.0 0.0
10 | 0.0 1.0 0.0 0.0
11 | 0.0 0.0 1.0 0.0]
12 |
13 | C = [sigma 0.0 0.0 0.0]'
14 | G = [1.0 0.0 0.0 0.0]
15 |
16 | T = 30
17 | ar = LSS(A, C, G, mu_0=ones(4))
18 |
19 | ymin, ymax = -0.8, 1.25
20 |
21 | ys = []
22 | yTs = []
23 |
24 | for i=1:20
25 | x, y = simulate(ar, T+15)
26 | y = vec(y)
27 | push!(ys, y)
28 | push!(yTs, y[T])
29 | end
30 | p1 = plot(ys, linewidth=1, alpha=0.5)
31 | scatter!(fill(T, length(yTs)), yTs, color=:black)
32 | plot!(ylims=(ymin, ymax), xticks=[], ylabel="y_t")
33 | vline!([T], color=:black, legend=:none)
34 | annotate!(T+1, -0.8, "T")
35 |
36 | p2 = histogram(yTs, bins=16, normed=true, orientation=:h, alpha=0.5)
37 | plot!(ylims=(ymin, ymax))
38 | plot(p1, p2, layout=2, legend=:none)
39 |
--------------------------------------------------------------------------------
/.github/workflows/format.yml:
--------------------------------------------------------------------------------
1 | name: Format Markdown Files
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - 'skip-for-now' # - '*'
7 |
8 | jobs:
9 | format:
10 | if: '! github.event.pull_request.draft'
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - name: Checkout repository
15 | uses: actions/checkout@v6
16 |
17 | - name: Setup Julia
18 | uses: julia-actions/setup-julia@v2
19 | with:
20 | version: 1.12.3
21 |
22 | - name: Install JuliaFormatter.jl
23 | run: julia -e 'import Pkg; Pkg.add("JuliaFormatter")'
24 |
25 | - name: Get Changed Files
26 | id: changed_files
27 | uses: tj-actions/changed-files@v47.0.1
28 | with:
29 | files: |
30 | **/*.md
31 |
32 | - name: Format Markdown Files
33 | run: |
34 | for file in ${{ steps.changed_files.outputs.all_changed_files }}; do
35 | julia format_myst.jl "$file"
36 | done
37 | env:
38 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
39 |
40 | - name: Commit changes
41 | run: |
42 | git config --local user.email "action@github.com"
43 | git config --local user.name "GitHub Action"
44 | git add .
45 | git diff-index --quiet HEAD || git commit -m "Apply formatting to Markdown files"
46 | env:
47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48 |
49 | - name: Push changes
50 | uses: ad-m/github-push-action@master
51 | with:
52 | github_token: ${{ secrets.GITHUB_TOKEN }}
53 | branch: ${{ github.head_ref }}
54 |
--------------------------------------------------------------------------------
/.github/workflows/cache.yml:
--------------------------------------------------------------------------------
1 | name: Build Cache
2 | on:
3 | push:
4 | branches:
5 | - main
6 | schedule:
7 | # Run monthly to avoid stale cache
8 | - cron: '0 0 1 * *'
9 | jobs:
10 | cache:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout
14 | uses: actions/checkout@v6
15 | - name: Set up Python
16 | uses: actions/setup-python@v6
17 | with:
18 | python-version: 3.11
19 | - name: Install Python Dependencies
20 | run: |
21 | pip install -r requirements.txt
22 | - name: Install LaTeX dependencies
23 | run: |
24 | sudo apt-get -qq update
25 | sudo apt-get install -y \
26 | texlive-latex-recommended \
27 | texlive-latex-extra \
28 | texlive-fonts-recommended \
29 | texlive-fonts-extra \
30 | texlive-xetex \
31 | latexmk \
32 | xindy \
33 | texlive-luatex \
34 | dvipng \
35 | ghostscript \
36 | cm-super
37 | - name: Set up Julia
38 | uses: julia-actions/setup-julia@v2
39 | with:
40 | version: 1.12.3
41 | - name: Install IJulia and Setup Project
42 | shell: bash
43 | run: |
44 | julia -e 'using Pkg; Pkg.add("IJulia");'
45 | julia --project=lectures --threads auto -e 'using Pkg; Pkg.instantiate();'
46 | - name: Build HTML
47 | shell: bash -l {0}
48 | run: |
49 | jb build lectures --path-output ./
50 | - name: Upload the "_build" folder (cache)
51 | uses: actions/upload-artifact@v6
52 | with:
53 | name: build-cache
54 | path: _build
55 | include-hidden-files: true
56 |
--------------------------------------------------------------------------------
/prompts/enzyme_test.jl:
--------------------------------------------------------------------------------
1 | using Enzyme, LinearAlgebra, EnzymeTestUtils
2 |
3 | # 1. Define the Cache Struct
4 | struct SimCache{T}
5 | tmp_vec::Vector{T}
6 | tmp_mat::Matrix{T}
7 | end
8 |
9 | # Helper to build it (good for users)
10 | function alloc_cache(n)
11 | SimCache(zeros(n), zeros(n, n))
12 | end
13 |
14 | # 2. The In-Place Function
15 | # Order: out, x (input), cache (buffers)
16 | function simulate!(out, x, cache::SimCache)
17 | # unpack for clarity
18 | tmp = cache.tmp_vec
19 |
20 | # Example: Intermediate computation that needs a buffer
21 | # If we didn't have cache, this line would allocate
22 | @. tmp = x * x + 2
23 |
24 | # Write to out
25 | @. out = tmp^2
26 | return nothing
27 | end
28 |
29 | # 3. Setup for Enzyme
30 | n = 100
31 | x = rand(n)
32 | out = zeros(n)
33 | cache = alloc_cache(n)
34 |
35 | # Create "Shadows" (gradients)
36 | # Enzyme.make_zero creates a structural copy with all zeros
37 | dx = Enzyme.make_zero(x)
38 | dout = Enzyme.make_zero(out) # "Seed" for the gradient (e.g., set to 1s if scalar)
39 | dcache = Enzyme.make_zero(cache) # The shadow workspace!
40 |
41 | # Initialize the seed (e.g., we want gradient of sum(out))
42 | dout .= 1.0
43 |
44 | # 4. The Call
45 | # Note: We pass Duplicated for the cache because it is MUTATED.
46 | autodiff(Reverse, simulate!,
47 | Duplicated(out, dout),
48 | Duplicated(x, dx),
49 | Duplicated(cache, dcache)
50 | )
51 |
52 |
53 | # 1. Setup Data
54 | x = randn(10)
55 | out = zeros(10)
56 | cache = alloc_cache(10) # User-defined helper to build cache struct
57 |
58 | # 2. Test Gradient of `x`
59 | # We use `test_reverse` to compare AD against Finite Differences.
60 | # Note: `out` and `cache` are mutated, so they MUST be Duplicated.
61 | test_reverse(simulate!, Const,
62 | (out, Duplicated), # Mutated Output
63 | (x, Duplicated), # Input (Active for differentiation)
64 | (cache, Duplicated) # Mutated Workspace
65 | )
66 |
67 | test_forward(simulate!, Const,
68 | (out, Duplicated),
69 | (x, Duplicated),
70 | (cache, Duplicated)
71 | )
--------------------------------------------------------------------------------
/prompts/simulation_prompt.md:
--------------------------------------------------------------------------------
1 | # Background and Guidelines
2 | I am trying to add lecture notes which show differentiable simulation in Julia using Enzyme.jl. We will add these to various lectures when they are complete.
3 |
4 | You are an expert Julia developer specializing in high-performance computing, zero-allocation patterns, and auto-differentiation. When writing code, prioritize strict memory management and in-place operations. Adhere to the following guidelines`:
5 | - See ./AGENTS.md for more details and look at programming patterns in the code examples as required.
6 | - Read ./prompts/differentiation.md for specific Enzyme.jl coding patterns and inplace.
7 | - You can create a .jl file and then run it with `julia --project=lectures ...` since that project and manifest file are already set up with Enzyme and all dependencies.
8 | - Do not add new dependencies unless absolutely necessary.
9 | - Our primary AD target is Enzyme.jl.
10 | - However, it has some constraints on usage. In particular, it does not support allocation inside of differentiable functions (e.g., avoids garbage collection). See ./prompts/differentiation.md for specific coding patterns to follow when writing Enzyme-differentiable Julia code.
11 |
12 | # Notation for Linear State Space Models
13 | If using a LSS, the math notation/formulation is as follows:
14 | $$
15 | x_{t+1} = A x_t + C w_{t+1}
16 | y_t = G x_t + H v_t
17 | $$
18 | where
19 | - w_{t+1} ~ N(0, I
20 | - v_t ~ N(0, I).
21 | - x_t \in R^N
22 | - y_t \in R^M
23 | - w_{t+1} \in R^K
24 | - v_t \in R^L.
25 | - A \in R^{N x N}, C \in R^{N x K}, G \in R^{M x N}, H \in R^{M x L}.
26 | - In cases with an initial prior x_0 ~ N(mu_0, Sigma_0) if normal
27 |
28 | # Task
29 | ### STEP 1:
30 | I want to show first code for an inplace simulation of a LSS model. Write a function with signature
31 | ```julia
32 | simulate_lss!(x, y, A, C, G, H, x_0, w, v)
33 | ```
34 | - The simulation length is implicit in the `w` and `v`. i.e., T = length(w) and I believe that v is then of size T+1
35 | - The output `x` and `y` are preallocated arrays of size (N, T+1) and (M, T+1) respectively. Organize the column vs. row ordering to ensure cache contiguity.
36 | I do not believe it needs a cache in this case since it would modify the `x` and `y` in place.
37 | - When you have that function write a simple example with $N = 3, M = 2, K = 2, L = 2$ and $T = 10$ where you either randomly choose the matrices or pick something reasonable (start with small `C` and `H` to avoid dominating noise). Draw the random normal shocks with `randn`.
38 | - Use plots to show the output of the `x` and `y` time series.
39 |
40 | Let me know when you have written this as a nice, clean jl file in ./lectures/more_julia/differentiable_simulation.jl
41 |
--------------------------------------------------------------------------------
/lectures/Project.toml:
--------------------------------------------------------------------------------
1 | name = "quantecon-notebooks-julia"
2 | version = "0.10.0"
3 | authors = ["quantecon "]
4 |
5 | [deps]
6 | Arpack = "7d9fca2a-8960-54d3-9f78-7d1dccf2cb97"
7 | BandedMatrices = "aae01518-5342-5314-be14-df237901396f"
8 | BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
9 | ControlSystems = "a6e380b2-a6ca-5380-bf3e-84a91bcd477e"
10 | DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
11 | DataInterpolations = "82cc6244-b520-54b8-b5a6-8a565e85f1d0"
12 | Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
13 | Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9"
14 | EnzymeTestUtils = "12d8515a-0907-448a-8884-5fe00fdf1c5a"
15 | FastGaussQuadrature = "442a2c76-b920-505d-bb47-c5924d526838"
16 | FixedPointAcceleration = "817d07cb-a79a-5c30-9a31-890123675176"
17 | ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
18 | Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
19 | IncompleteLU = "40713840-3770-5561-ab4c-a76e7d0d7895"
20 | Integrals = "de52edbc-65ea-441a-8357-d3a637375a31"
21 | Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
22 | IterativeSolvers = "42fd0dbc-a981-5370-80f2-aaf504508153"
23 | KernelDensity = "5ab0869b-81aa-558d-bb23-cbf5423bbe9b"
24 | LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
25 | Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
26 | LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
27 | LinearMaps = "7a12625a-238d-50fd-b39a-03d52299707e"
28 | LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
29 | LoopVectorization = "bdcacae8-1622-11e9-2a5c-532679323890"
30 | MatrixEquations = "99c1a7ee-ab34-5fd5-8076-27c950a045f4"
31 | NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56"
32 | NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
33 | Optim = "429524aa-4258-5aef-a3af-852621145aeb"
34 | Optimization = "7f7a1694-90dd-40f0-9382-eb1efda571ba"
35 | OptimizationOptimJL = "36348300-93cb-4f02-beb5-3c3902f8871e"
36 | OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
37 | Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
38 | Polynomials = "f27b6e38-b328-58d1-80ce-0feddd5e7a45"
39 | Preconditioners = "af69fa37-3177-5a40-98ee-561f696e4fcd"
40 | QuadGK = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
41 | QuantEcon = "fcd29c91-0bd7-5a09-975d-7ac3f643a60c"
42 | Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
43 | Roots = "f2b01f46-fcfa-551c-844a-d8ac1e96c665"
44 | SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
45 | SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
46 | StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
47 | Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
48 | StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd"
49 | StochasticDiffEq = "789caeaf-c7a9-5a7d-9973-96adeb23e2a0"
50 | Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
51 | Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
52 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Build Project [using jupyter-book]
2 | on: [pull_request]
3 | jobs:
4 | build:
5 | if: '! github.event.pull_request.draft'
6 | runs-on: ubuntu-latest
7 | steps:
8 | - name: Checkout
9 | uses: actions/checkout@v6
10 | - name: Set up Python
11 | uses: actions/setup-python@v6
12 | with:
13 | python-version: 3.11
14 | - name: Install Python Dependencies
15 | run: |
16 | pip install -r requirements.txt
17 | - name: Install LaTeX dependencies
18 | run: |
19 | sudo apt-get -qq update
20 | sudo apt-get install -y \
21 | texlive-latex-recommended \
22 | texlive-latex-extra \
23 | texlive-fonts-recommended \
24 | texlive-fonts-extra \
25 | texlive-xetex \
26 | latexmk \
27 | xindy \
28 | texlive-luatex \
29 | dvipng \
30 | ghostscript \
31 | cm-super
32 | - name: Set up Julia
33 | uses: julia-actions/setup-julia@v2
34 | with:
35 | version: 1.12.3
36 | - name: Install IJulia and Setup Project
37 | shell: bash
38 | run: |
39 | julia -e 'using Pkg; Pkg.add("IJulia");'
40 | julia --project=lectures --threads auto -e 'using Pkg; Pkg.instantiate();'
41 | # Download Jupyter Book Cache
42 | - name: Download "build" folder (cache)
43 | uses: dawidd6/action-download-artifact@v11
44 | with:
45 | workflow: cache.yml
46 | branch: main
47 | name: build-cache
48 | path: _build
49 | # Build Assets (Download Notebooks and PDF via LaTeX)
50 | # - name: Build PDF from LaTeX
51 | # shell: bash -l {0}
52 | # run: |
53 | # jb build lectures --builder pdflatex --path-output ./ -n --keep-going
54 | # mkdir -p _build/html/_pdf
55 | # cp -u _build/latex/*.pdf _build/html/_pdf
56 | - name: Build Download Notebooks (sphinx-tojupyter)
57 | shell: bash -l {0}
58 | run: |
59 | jb build lectures --path-output ./ --builder=custom --custom-builder=jupyter -W --keep-going
60 | mkdir -p _build/html/_notebooks
61 | rsync -r _build/jupyter/ _build/html/_notebooks/
62 | # Build HTML (Website)
63 | - name: Build HTML
64 | shell: bash -l {0}
65 | run: |
66 | jb build lectures --path-output ./
67 | - name: Save Build as Artifact
68 | uses: actions/upload-artifact@v6
69 | with:
70 | name: _build
71 | path: _build
72 | - name: Preview Deploy to Netlify
73 | uses: nwtgck/actions-netlify@v3.0.0
74 | with:
75 | publish-dir: '_build/html/'
76 | production-branch: master
77 | github-token: ${{ secrets.GITHUB_TOKEN }}
78 | deploy-message: "Preview Deploy from GitHub Actions"
79 | env:
80 | NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
81 | NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
82 |
--------------------------------------------------------------------------------
/lectures/troubleshooting.md:
--------------------------------------------------------------------------------
1 | ---
2 | jupytext:
3 | text_representation:
4 | extension: .md
5 | format_name: myst
6 | kernelspec:
7 | display_name: Julia
8 | language: julia
9 | name: julia-1.12
10 | ---
11 |
12 | (troubleshooting)=
13 | ```{raw} html
14 |
19 | ```
20 |
21 | # Troubleshooting
22 |
23 | ```{contents} Contents
24 | :depth: 2
25 | ```
26 |
27 | This troubleshooting page is to help ensure you software environment is setup correctly
28 | to run this lecture set locally on your machine.
29 |
30 | ## Resetting your Lectures
31 |
32 | Using VS Code, you can easily revert back individual lectures, all of the lectures, or get updated versions of the lecture notes.
33 |
34 | See the lecture on [setting up your environment](reset_notebooks) for more.
35 |
36 | If the `Project.toml` or `Manifest.toml` files are modified, then you may want to redo the [instantiation](install_packages) step to ensure you have the correct versions.
37 |
38 |
39 | (reset_julia)=
40 | ## Fixing Your Local Environment
41 |
42 | If packages are misbehaving, you may want to simply [reset the lectures](reset_notebooks) or at least the `Project.toml` and `Manifest.toml` files from the lecture notes, and then redo the [instantiation](install_packages) step This will fix nearly every problem.
43 |
44 | However, if you are still having issues you could delete the entire `.julia` directory for your users, and then redo the installation of packages as well as `] add IJulia`. It is fast for recent versions of Julia.
45 |
46 | The directory is located in your user directory (e.g. `~/.julia` on MacOS and Linux, and `C:\Users\YOURUSERNAME\.julia` on Windows) or you can find this directory by running `DEPOT_PATH[1]` in a Julia REPL.
47 |
48 | ## Upgrading Julia
49 |
50 | You should be able to upgrade Julia by simply
51 | - Installing the latest release from the [Julia website](https://julialang.org/downloads/).
52 | - Uninstalling your old release (so that the VS Code extension only uses the newest version)
53 | - And, finally, you will need to redo the `] add IJulia` [installation step](intro_repl) to ensure that Jupyter knows how to find the new version.
54 |
55 | ```{warning}
56 | While upgrading Julia will typically work with the notebooks, there may be upgrades where a particular lecture has problems. Make sure that you have [updated your notebooks](reset_notebooks) in case bug fixes were made, and post an issue to the [GitHub source for these lectures](https://github.com/QuantEcon/lecture-julia.myst/issues).
57 | ```
58 |
59 | ## Reporting an Issue
60 |
61 | One way to give feedback is to raise an issue through our [issue tracker](https://github.com/QuantEcon/lecture-julia.myst/issues).
62 |
63 | Please be as specific as possible. Tell us where the problem is and as much
64 | detail about your local set up as you can provide.
65 |
66 | Another feedback option is to use our [discourse forum](https://discourse.quantecon.org/).
67 |
68 | Finally, you can provide direct feedback to [contact@quantecon.org](mailto:contact@quantecon.org)
69 |
70 |
--------------------------------------------------------------------------------
/lectures/_toc.yml:
--------------------------------------------------------------------------------
1 | format: jb-book
2 | root: intro
3 | parts:
4 | - caption: Getting Started with Julia
5 | numbered: true
6 | chapters:
7 | - file: getting_started_julia/getting_started
8 | - file: getting_started_julia/julia_by_example
9 | - file: getting_started_julia/julia_essentials
10 | - file: getting_started_julia/fundamental_types
11 | - file: getting_started_julia/introduction_to_types
12 | - caption: Package Ecosystem
13 | numbered: true
14 | chapters:
15 | - file: more_julia/generic_programming
16 | - file: more_julia/auto_differentiation
17 | - file: more_julia/quadrature_interpolation
18 | - file: more_julia/data_statistical_packages
19 | - file: more_julia/optimization_solver_packages
20 | - caption: Software Engineering
21 | numbered: true
22 | chapters:
23 | - file: software_engineering/tools_editors
24 | - file: software_engineering/version_control
25 | - file: software_engineering/testing
26 | - file: software_engineering/need_for_speed
27 | - caption: Tools and Techniques
28 | numbered: true
29 | chapters:
30 | - file: tools_and_techniques/geom_series
31 | - file: tools_and_techniques/linear_algebra
32 | - file: tools_and_techniques/orth_proj
33 | - file: tools_and_techniques/lln_clt
34 | - file: tools_and_techniques/stationary_densities
35 | - file: tools_and_techniques/numerical_linear_algebra
36 | - file: tools_and_techniques/iterative_methods_sparsity
37 | - file: tools_and_techniques/differentiable_dynamics
38 | - caption: Introduction to Dynamics
39 | numbered: true
40 | chapters:
41 | - file: introduction_dynamics/scalar_dynam
42 | - file: introduction_dynamics/ar1_processes
43 | - file: introduction_dynamics/finite_markov
44 | - file: introduction_dynamics/linear_models
45 | - file: introduction_dynamics/wealth_dynamics
46 | - file: introduction_dynamics/kalman
47 | - file: introduction_dynamics/short_path
48 | - caption: Dynamic Programming
49 | numbered: true
50 | chapters:
51 | - file: dynamic_programming/mccall_model
52 | - file: dynamic_programming/mccall_model_with_separation
53 | - file: dynamic_programming/wald_friedman
54 | - file: dynamic_programming/odu
55 | - file: dynamic_programming/career
56 | - file: dynamic_programming/jv
57 | - file: dynamic_programming/optgrowth
58 | - file: dynamic_programming/coleman_policy_iter
59 | - file: dynamic_programming/egm_policy_iter
60 | - file: dynamic_programming/lqcontrol
61 | - file: dynamic_programming/perm_income
62 | - file: dynamic_programming/perm_income_cons
63 | - file: dynamic_programming/smoothing
64 | - file: dynamic_programming/ifp
65 | - file: dynamic_programming/robustness
66 | - file: dynamic_programming/discrete_dp
67 | - caption: Modeling in Continuous Time
68 | numbered: true
69 | chapters:
70 | - file: continuous_time/seir_model
71 | - file: continuous_time/covid_sde
72 | - caption: Multiple Agent Models
73 | numbered: true
74 | chapters:
75 | - file: multi_agent_models/schelling
76 | - file: multi_agent_models/lake_model
77 | - file: multi_agent_models/rational_expectations
78 | - file: multi_agent_models/markov_perf
79 | - file: multi_agent_models/markov_asset
80 | - file: multi_agent_models/lucas_model
81 | - file: multi_agent_models/harrison_kreps
82 | - file: multi_agent_models/uncertainty_traps
83 | - file: multi_agent_models/aiyagari
84 | - file: multi_agent_models/arellano
85 | - file: multi_agent_models/matsuyama
86 | - caption: Other
87 | numbered: true
88 | chapters:
89 | - file: about_lectures
90 | - file: troubleshooting
91 | - file: zreferences
92 | - file: status
93 |
--------------------------------------------------------------------------------
/lectures/_config.yml:
--------------------------------------------------------------------------------
1 | title: Quantitative Economics with Julia
2 | author: Jesse Perla & Thomas J. Sargent & John Stachurski
3 | logo: _static/qe-logo-large.png
4 | description: This website presents a set of lectures on quantitative economic modeling, designed and written by Jesse Perla, Thomas J. Sargent and John Stachurski. The language instruction is Julia.
5 |
6 | execute:
7 | execute_notebooks: "cache"
8 | timeout: 600
9 |
10 | bibtex_bibfiles:
11 | - _static/quant-econ.bib
12 |
13 | html:
14 | baseurl: https://julia.quantecon.org/
15 |
16 | latex:
17 | latex_documents:
18 | targetname: quantecon-julia.tex
19 |
20 | sphinx:
21 | extra_extensions: [sphinx_multitoc_numbering, sphinxext.rediraffe, sphinx_tojupyter]
22 | config:
23 | nb_mime_priority_overrides: [
24 | # HTML
25 | ['html', 'application/vnd.jupyter.widget-view+json', 10],
26 | ['html', 'application/javascript', 20],
27 | ['html', 'text/html', 30],
28 | ['html', 'text/latex', 40],
29 | ['html', 'image/svg+xml', 50],
30 | ['html', 'image/png', 60],
31 | ['html', 'image/jpeg', 70],
32 | ['html', 'text/markdown', 80],
33 | ['html', 'text/plain', 90],
34 | # Jupyter Notebooks
35 | ['jupyter', 'application/vnd.jupyter.widget-view+json', 10],
36 | ['jupyter', 'application/javascript', 20],
37 | ['jupyter', 'text/html', 30],
38 | ['jupyter', 'text/latex', 40],
39 | ['jupyter', 'image/svg+xml', 50],
40 | ['jupyter', 'image/png', 60],
41 | ['jupyter', 'image/jpeg', 70],
42 | ['jupyter', 'text/markdown', 80],
43 | ['jupyter', 'text/plain', 90],
44 | # LaTeX
45 | ['latex', 'text/latex', 10],
46 | ['latex', 'application/pdf', 20],
47 | ['latex', 'image/png', 30],
48 | ['latex', 'image/jpeg', 40],
49 | ['latex', 'text/markdown', 50],
50 | ['latex', 'text/plain', 60],
51 | # Link Checker
52 | ['linkcheck', 'text/plain', 10],
53 | ]
54 | highlight_language: julia
55 | html_favicon: _static/lectures-favicon.ico
56 | html_theme: quantecon_book_theme
57 | html_static_path: ['_static']
58 | html_theme_options:
59 | authors:
60 | - name: Jesse Perla
61 | url: https://www.jesseperla.com
62 | - name: Thomas J. Sargent
63 | url: http://www.tomsargent.com/
64 | - name: John Stachurski
65 | url: https://johnstachurski.net/
66 | dark_logo: quantecon-logo-transparent.png
67 | header_organisation_url: https://quantecon.org
68 | header_organisation: QuantEcon
69 | repository_url: https://github.com/quantecon/lecture-julia.myst
70 | repository_branch: main
71 | nb_repository_url: https://github.com/quantecon/lecture-julia.notebooks
72 | nb_branch: main
73 | twitter: quantecon
74 | twitter_logo_url: https://assets.quantecon.org/img/qe-twitter-logo.png
75 | og_logo_url: https://assets.quantecon.org/img/qe-og-logo.png
76 | description: This website presents a set of lectures on quantitative economic modeling, designed and written by Jesse Perla, Thomas J. Sargent and John Stachurski. The language instruction is Julia.
77 | keywords: Julia, QuantEcon, Quantitative Economics, Economics, Sloan, Alfred P. Sloan Foundation, Tom J. Sargent, John Stachurski
78 | analytics:
79 | google_analytics_id: G-3PCWRLGWND
80 | launch_buttons:
81 | colab_url: https://colab.research.google.com
82 | mathjax3_config:
83 | tex:
84 | macros:
85 | "argmax" : "arg\\,max"
86 | "argmin" : "arg\\,min"
87 | mathjax_path: https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
88 | rediraffe_redirects:
89 | index_toc.md: intro.md
90 | tojupyter_default_lang: julia
91 | tojupyter_lang_synonyms: ['julia-1.12']
92 | tojupyter_static_file_path: ["source/_static", "_static"]
93 | tojupyter_target_html: true
94 | tojupyter_urlpath: "https://julia.quantecon.org/"
95 | tojupyter_image_urlpath: "https://julia.quantecon.org/_static/"
96 | tojupyter_kernels:
97 | julia:
98 | kernelspec:
99 | display_name: Julia
100 | language: julia
101 | name: julia-1.12
102 | tojupyter_images_markdown: true
103 |
--------------------------------------------------------------------------------
/format_myst.jl:
--------------------------------------------------------------------------------
1 | # Utility to run JuliaFormatter.jl on the julia code within myst markdown files
2 | # Written for CLI acccess: for example, call it with
3 | # julia format_myst.jl lectures/getting_started_julia/getting_started.md
4 |
5 | # Test with the following examples:
6 | # format_myst("lectures/getting_started_julia/getting_started.md", "lectures/getting_started_julia/getting_started2.md")
7 | # format_myst!("lectures/getting_started_julia/getting_started.md")
8 | using JuliaFormatter
9 |
10 | # Substrings with unicode don't work very well
11 | substring(str, start, stop) = str[nextind(str, 0, start):nextind(str, 0, stop)]
12 |
13 | # inplace modification
14 | function format_myst!(input_file_path, extra_replacements = false,
15 | ignore_errors = false)
16 | format_myst(input_file_path, input_file_path, extra_replacements, ignore_errors)
17 | end
18 | function format_myst(input_file_path, output_file_path, extra_replacements = false,
19 | ignore_errors = false)
20 | # It has one capturing group which corresponds to the code inside the block
21 | code_block_pattern = r"(```{code-cell} julia\n)([\s\S]*?)(\n```)"
22 |
23 | # Extract config files/etc. Requires a .JuliaFormatter.toml file
24 | config_file = JuliaFormatter.find_config_file(".")
25 | style = pop!(config_file, "style")
26 | config = Dict(Symbol(a) => b for (a, b) in config_file)
27 |
28 | function format_code_block(m)
29 | try
30 | # m is the whole match, including the start and end markers
31 | block_length = length(m)
32 | start_marker = substring(m, 1, 21) # length of ```{code-cell} julia\n
33 | code = String(substring(m, 22, block_length - 4))
34 | end_marker = substring(m, block_length - 3, block_length)
35 |
36 | # don't transform if it has myst tags
37 | if substring(code, 1, min(length(code), 3)) == "---"
38 | return m
39 | end
40 |
41 | # Use Julia Formatter and the loaded style file
42 | transformed_code = format_text(code, style; config...)
43 |
44 | # Return the new block
45 | return start_marker * transformed_code * end_marker
46 | catch e
47 | println("Failed to format code block:")
48 | print(m)
49 | if ignore_errors
50 | return m # i.e., don't change anything
51 | else
52 | throw(e)
53 | end
54 | end
55 | end
56 |
57 | # Additional replacements are optional. This may be useful when replacing variable names to make it easier to type in ascii
58 | replacements = Dict("α" => "alpha", "β" => "beta", "γ" => "gamma", "≤" => "<=",
59 | "≥" => ">=", "Σ" => "Sigma", "σ" => "sigma","μ"=>"mu","ϕ"=>"phi","ψ"=>"psi","ϵ"=>"epsilon",
60 | "δ"=>"delta","θ" => "theta","ζ"=>"zeta","X̄" => "X_bar","p̄" => "p_bar","x̂" => "x_hat","λ"=>"lambda",
61 | "ρ"=>"rho","u′" => "u_prime" , "f′"=>"f_prime"," ∂u∂c"=>"dudc","Π"=>"Pi","π"=>"pi","ξ"=>"xi","c̄"=>"c_bar",
62 | "w̄"=>"w_bar","Θ" => "Theta", "Ξ" =>"Xi", "Q̃" => "Q_tilde","R̃" => "R_tilde","Ã" => "A_tilde", "B̃" => "B_tilde",
63 | "P̃" => "P_tilde","F̃" => "F_tilde","d̃" => "d_tilde")
64 |
65 | # Replace the code blocks in the content and handle exceptions
66 | try
67 | # Read in the file
68 | file_content = read(input_file_path, String)
69 |
70 | new_content = replace(file_content,
71 | code_block_pattern => format_code_block)
72 |
73 | if extra_replacements # optional
74 | new_content = replace(new_content, replacements...)
75 | end
76 |
77 | open(output_file_path, "w") do f
78 | write(f, new_content)
79 | end
80 | return true
81 | catch e
82 | println("Failed to process the markdown file at $input_file_path")
83 | print(e)
84 | return false
85 | end
86 | end
87 |
88 | if length(ARGS) == 0
89 | println("Please provide a file path to a myst markdown file")
90 | exit(1)
91 | else
92 | use_extra_replacements = length(ARGS) > 1 && ARGS[2] == "true"
93 | print("Replacing file at $(ARGS[1]) with formatted version. Additional replacements = $use_extra_replacements\n")
94 | success = format_myst!(ARGS[1],use_extra_replacements)
95 | success || exit(1)
96 | end
--------------------------------------------------------------------------------
/lectures/tools_and_techniques/differentiable_simulation.jl:
--------------------------------------------------------------------------------
1 | using LinearAlgebra, Random, Plots, Test, Enzyme, Statistics
2 |
3 | struct LSS{TA, TC, TG, TH}
4 | A::TA
5 | C::TC
6 | G::TG
7 | H::TH
8 | end
9 |
10 | # state and observation paths are stored column-wise for cache-friendly access
11 | function simulate_lss!(x, y, model::LSS, x_0, w, v)
12 | (; A, C, G, H) = model
13 | N, x_cols = size(x)
14 | M, y_cols = size(y)
15 | T = size(w, 2)
16 |
17 | @assert size(A) == (N, N)
18 | @assert size(C, 1) == N
19 | @assert size(G) == (M, N)
20 | @assert size(H, 1) == M
21 | @assert size(w, 1) == size(C, 2)
22 | @assert size(v, 1) == size(H, 2)
23 | @assert size(v, 2) == T + 1
24 | @assert x_cols == T + 1
25 | @assert y_cols == T + 1
26 | @assert length(x_0) == N
27 |
28 | # Enzyme has challenges with activity analysis on broadcasting assignments
29 | @inbounds for i in 1:N
30 | x[i, 1] = x_0[i]
31 | end
32 |
33 | @inbounds for t in 1:T
34 | @views mul!(x[:, t + 1], A, x[:, t])
35 | # x_{t+1} = A x_t + C w_{t+1}; (1.0, 1.0) adds C w_{t+1} into the existing A x_t
36 | @views mul!(x[:, t + 1], C, w[:, t], 1.0, 1.0)
37 |
38 | @views mul!(y[:, t], G, x[:, t])
39 | # y_t = G x_t + H v_t; (1.0, 1.0) accumulates H v_t into the G x_t buffer
40 | @views mul!(y[:, t], H, v[:, t], 1.0, 1.0)
41 | end
42 |
43 | @views mul!(y[:, T + 1], G, x[:, T + 1])
44 | # y_{T+1} = G x_{T+1} + H v_{T+1}
45 | @views mul!(y[:, T + 1], H, v[:, T + 1], 1.0, 1.0)
46 |
47 | return nothing
48 | end
49 |
50 | function mean_first_observation(x, y, model, x_0, w, v)
51 | simulate_lss!(x, y, model, x_0, w, v)
52 | out = mean(@view y[1, :])
53 | return out
54 | end
55 |
56 | Random.seed!(1234)
57 |
58 | N = 3
59 | M = 2
60 | K = 2
61 | L = 2
62 | T = 10
63 |
64 | A = [0.8 0.1 0.0
65 | 0.0 0.7 0.1
66 | 0.0 0.0 0.6]
67 | C = 0.1 .* randn(N, K)
68 | G = [1.0 0.0 0.0
69 | 0.0 1.0 0.3]
70 | H = 0.05 .* randn(M, L)
71 | model = LSS(A, C, G, H)
72 |
73 | x_0 = randn(N)
74 | w = randn(K, T)
75 | v = randn(L, T + 1)
76 |
77 | x = zeros(N, T + 1)
78 | y = zeros(M, T + 1)
79 |
80 | simulate_lss!(x, y, model, x_0, w, v)
81 |
82 | # Forward-mode sensitivity of full state/observation paths to w[1]
83 | x_w = zeros(N, T + 1)
84 | y_w = zeros(M, T + 1)
85 | dx_w = Enzyme.make_zero(x_w)
86 | dy_w = Enzyme.make_zero(y_w)
87 | dw = Enzyme.make_zero(w)
88 | dw[1] = one(eltype(w))
89 | autodiff(
90 | Forward,
91 | simulate_lss!,
92 | Duplicated(x_w, dx_w),
93 | Duplicated(y_w, dy_w),
94 | Const(model),
95 | Const(x_0),
96 | Duplicated(w, dw),
97 | Const(v),
98 | )
99 |
100 | dw_rev = zero(w)
101 | x_rev = zeros(N, T + 1)
102 | y_rev = zeros(M, T + 1)
103 | dx_rev = Enzyme.make_zero(x_rev)
104 | dy_rev = Enzyme.make_zero(y_rev)
105 |
106 | autodiff(
107 | Reverse,
108 | mean_first_observation,
109 | Duplicated(x_rev, dx_rev),
110 | Duplicated(y_rev, dy_rev),
111 | Const(model),
112 | Const(x_0),
113 | Duplicated(w, dw_rev),
114 | Const(v),
115 | )
116 |
117 | @test all(isfinite, dw_rev)
118 |
119 | @testset "batch tangents for A" begin
120 | x_batch = zeros(N, T + 1)
121 | y_batch = zeros(M, T + 1)
122 | dxs = (Enzyme.make_zero(x_batch), Enzyme.make_zero(x_batch))
123 | dys = (Enzyme.make_zero(y_batch), Enzyme.make_zero(y_batch))
124 | dmodels = (Enzyme.make_zero(model), Enzyme.make_zero(model))
125 | dmodels[1].A[1] = one(eltype(A))
126 | dmodels[2].A[2] = one(eltype(A))
127 |
128 | autodiff(
129 | Forward,
130 | simulate_lss!,
131 | BatchDuplicated(x_batch, dxs),
132 | BatchDuplicated(y_batch, dys),
133 | BatchDuplicated(model, dmodels),
134 | Const(x_0),
135 | Const(w),
136 | Const(v),
137 | )
138 |
139 | @test maximum(abs, dxs[1]) > 0
140 | @test maximum(abs, dys[1]) > 0
141 | end
142 |
143 | time = 0:T
144 | fig_states = plot(
145 | time,
146 | x',
147 | lw = 2,
148 | xlabel = "t",
149 | ylabel = "state",
150 | label = ["x1", "x2", "x3"],
151 | title = "State Paths",
152 | )
153 |
154 | fig_observations = plot(
155 | time,
156 | y',
157 | lw = 2,
158 | xlabel = "t",
159 | ylabel = "observation",
160 | label = ["y1", "y2"],
161 | title = "Observation Paths",
162 | )
163 |
164 | display(fig_states)
165 | display(fig_observations)
166 |
--------------------------------------------------------------------------------
/wsl.md:
--------------------------------------------------------------------------------
1 | # WSL Editor Setup
2 | Editing on Windows is not entirely supported due to python/sphinx issues. Instead, on Windows use WSL with VS Code.
3 |
4 | ## Setup WSL and VS Code
5 |
6 | 1. To get "Ubuntu on Windows" and other linux kernels see [instructions](https://docs.microsoft.com/en-us/windows/wsl/install-win10).
7 |
8 | - Fresh install quick path (PowerShell as Administrator):
9 | ```
10 | wsl --install -d Ubuntu
11 | ```
12 | - **Note:** When typing your UNIX password during setup, nothing will appear on screen. This is normal — just type and press Enter.
13 |
14 | - If installation fails, ensure required features are enabled (Powershell as administrator):
15 | ```
16 | dism /online /get-features /format:table | findstr /i "Microsoft-Windows-Subsystem-Linux"
17 | dism /online /get-features /format:table | findstr /i "VirtualMachinePlatform"
18 | ```
19 | - If either is Disabled, enable and reboot:
20 |
21 | ```
22 | dism /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
23 | dism /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
24 |
25 | ```
26 |
27 | 2. Install [VSCode](https://code.visualstudio.com/) with remote WSL support on windows
28 | - See [VS Code Remote Editing](https://code.visualstudio.com/docs/remote/remote-overview)
29 | - [VS Code Remote WSL](https://code.visualstudio.com/docs/remote/wsl#_opening-a-terminal-in-wsl)
30 | 3. Clone this repository using VS Code on Windows
31 | 4. After you open it, choose `> WSL: Reopen in WSL Window` from the command palette (Ctrl+Shift+P) if you have setup WSL/etc. properly
32 | - If you are successful, the bottom left corner of VS Code will show `>< WSL:Ubuntu>`
33 | - Now any terminals you run should be the linux ubuntu terminals
34 |
35 | 5. Assuming you have `git` installed and setup properly on windows, to get git credentials integrated, in a windows terminal (i.e. not in WSL) run
36 | ```
37 | git config --global credential.helper wincred
38 | ```
39 | - Then in a WSL terminal (within VS Code or otherwise),
40 | ```
41 | git config --global user.email "you@example.com"
42 | git config --global user.name "Your Name"
43 | git config --global credential.helper "/mnt/c/Program\ Files/Git/mingw64/libexec/git-core/git-credential-wincred.exe"
44 | ```
45 | - (See more details in [Sharing Credentials](https://code.visualstudio.com/docs/remote/troubleshooting#_sharing-git-credentials-between-windows-and-wsl) )
46 |
47 |
48 | ## Setup Linux Packages/etc.
49 |
50 | 1. Start within your home directory in linux or in a WSL terminal
51 |
52 | 2. In a WSL terminal, Go to your home directory and make sure key dependencies are installed
53 | ```bash
54 | cd ~
55 | sudo apt update
56 | sudo apt-get upgrade
57 | sudo apt install make gcc unzip
58 | sudo apt-get update
59 | sudo apt install -y libxt6 libxrender1 libgl1 libgl1-mesa-dri libqt5widgets5
60 | ```
61 | 3. Install conda with the updated version of
62 | ```
63 | wget https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh
64 | bash Anaconda3-2024.06-1-Linux-x86_64.sh
65 | ```
66 | - accept default paths
67 | - accept licensing terms
68 | - *IMPORTANT* Manually choose `yes` to have it do the `conda init`
69 | 4. Install julia with [juliaup](https://github.com/JuliaLang/juliaup?tab=readme-ov-file#mac-linux-and-freebsd)
70 | ```bash
71 | curl -fsSL https://install.julialang.org | sh
72 | ```
73 | 5. Install key VSCode extensions (which are a separate set of installations for WSL vs. Windows)
74 | - Search for `python, julia, MyST-Markdown, Jupyter` and if you have support `GitHub Copilot, GitHub Copilot Chat`
75 | - Usually requires restart VS Code
76 | 6. In a terminal, create a virtual environment for conda and install packages
77 | ```bash
78 | conda create -n lecture-julia.myst python=3.11
79 | conda activate lecture-julia.myst
80 | pip install -r requirements.txt
81 | ```
82 | 7. Can try `> Python: Select Interpreter` and choose the `lecture-julia.myst` environment to make it automatic, but it does not always work.
83 | 8. Start a WSL terminal, make sure that the `lecture-julia.myst` is activated (and use `conda activate lecture-julia.myst` if not) then
84 | - Start `julia`, which be in your global environment with nothing installed. Can check with `]st`
85 | - Then install the Julia jupyter kernel with `] add IJulia`
86 | 9. Install the Julia packages required for the lecture notes, running in a terminal (assuming still at the root)
87 | ```bash
88 | julia --project=lectures --threads auto -e 'using Pkg; Pkg.instantiate();'
89 | ```
90 | - This should take 10-15 minutes the first time.
91 |
92 | At this point, you should be ready to follow the instructions in the main [README.md](./README.md)
93 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: Build & Publish to GH pages
2 | on:
3 | push:
4 | tags:
5 | - 'publish*'
6 | jobs:
7 | publish:
8 | if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout
12 | uses: actions/checkout@v6
13 | - name: Set up Python
14 | uses: actions/setup-python@v6
15 | with:
16 | python-version: 3.11
17 | - name: Install Python Dependencies
18 | run: |
19 | pip install -r requirements.txt
20 | - name: Install LaTeX dependencies
21 | run: |
22 | sudo apt-get -qq update
23 | sudo apt-get install -y \
24 | texlive-latex-recommended \
25 | texlive-latex-extra \
26 | texlive-fonts-recommended \
27 | texlive-fonts-extra \
28 | texlive-xetex \
29 | latexmk \
30 | xindy \
31 | texlive-luatex \
32 | dvipng \
33 | ghostscript \
34 | cm-super
35 | - name: Set up Julia
36 | uses: julia-actions/setup-julia@v2
37 | with:
38 | version: 1.12.3
39 | - name: Install IJulia and Setup Project
40 | shell: bash
41 | run: |
42 | julia -e 'using Pkg; Pkg.add("IJulia");'
43 | julia --project=lectures --threads auto -e 'using Pkg; Pkg.instantiate();'
44 | # Download Jupyter Book Cache
45 | - name: Download "build" folder (cache)
46 | uses: dawidd6/action-download-artifact@v11
47 | with:
48 | workflow: cache.yml
49 | branch: main
50 | name: build-cache
51 | path: _build
52 | # Build Assets (Download Notebooks and PDF via LaTeX)
53 | # - name: Build PDF from LaTeX
54 | # shell: bash -l {0}
55 | # run: |
56 | # jb build lectures --builder pdflatex --path-output ./ -n --keep-going
57 | # mkdir -p _build/html/_pdf
58 | # cp -u _build/latex/*.pdf _build/html/_pdf
59 | - name: Build Download Notebooks (sphinx-tojupyter)
60 | shell: bash -l {0}
61 | run: |
62 | jb build lectures --path-output ./ --builder=custom --custom-builder=jupyter
63 | zip -r download-notebooks.zip _build/jupyter
64 | - uses: actions/upload-artifact@v6
65 | with:
66 | name: download-notebooks
67 | path: download-notebooks.zip
68 | - name: Copy Download Notebooks for GH-PAGES
69 | shell: bash -l {0}
70 | run: |
71 | mkdir -p _build/html/_notebooks
72 | rsync -r _build/jupyter/ _build/html/_notebooks/
73 | # Build Website
74 | - name: Build HTML
75 | shell: bash -l {0}
76 | run: |
77 | jb build lectures --path-output ./
78 | # Create HTML archive for release assets
79 | - name: Create HTML archive
80 | shell: bash -l {0}
81 | run: |
82 | tar -czf lecture-julia-html-${{ github.ref_name }}.tar.gz -C _build/html .
83 | sha256sum lecture-julia-html-${{ github.ref_name }}.tar.gz > html-checksum.txt
84 |
85 | # Create metadata manifest
86 | cat > html-manifest.json << EOF
87 | {
88 | "tag": "${{ github.ref_name }}",
89 | "commit": "${{ github.sha }}",
90 | "timestamp": "$(date -Iseconds)",
91 | "size_mb": $(du -sm _build/html | cut -f1),
92 | "file_count": $(find _build/html -type f | wc -l)
93 | }
94 | EOF
95 | - name: Upload archives to release
96 | uses: softprops/action-gh-release@v2
97 | with:
98 | files: |
99 | lecture-julia-html-${{ github.ref_name }}.tar.gz
100 | html-checksum.txt
101 | html-manifest.json
102 | env:
103 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
104 | - name: Deploy website to gh-pages
105 | uses: peaceiris/actions-gh-pages@v4
106 | with:
107 | github_token: ${{ secrets.GITHUB_TOKEN }}
108 | publish_dir: _build/html/
109 | cname: julia.quantecon.org
110 | - name: Upload "_build" folder (cache)
111 | uses: actions/upload-artifact@v6
112 | with:
113 | name: build-publish
114 | path: _build
115 | # Sync Download Notebooks
116 | - name: Prepare lecture-julia.notebooks sync
117 | shell: bash
118 | run: |
119 | mkdir -p _build/lecture-julia.notebooks
120 | cp -a _notebook_repo/. _build/lecture-julia.notebooks
121 | cp -a _build/jupyter/. _build/lecture-julia.notebooks
122 | rm -rf _build/lecture-julia.notebooks/_static
123 | rm -rf _build/lecture-julia.notebooks/_panels_static
124 | cp lectures/Project.toml _build/lecture-julia.notebooks
125 | cp lectures/Manifest.toml _build/lecture-julia.notebooks
126 | ls -a _build/lecture-julia.notebooks
127 | - name: Commit notebooks to lecture-julia.notebooks
128 | shell: bash -l {0}
129 | env:
130 | QE_SERVICES_PAT: ${{ secrets.QUANTECON_SERVICES_PAT }}
131 | run: |
132 | git clone https://quantecon-services:$QE_SERVICES_PAT@github.com/quantecon/lecture-julia.notebooks
133 | cp -r _build/lecture-julia.notebooks/. lecture-julia.notebooks
134 | cd lecture-julia.notebooks
135 | git config user.name "QuantEcon Services"
136 | git config user.email "admin@quantecon.org"
137 | git add --all
138 | git commit -m "auto publishing updates to notebooks"
139 | git push origin main
140 |
--------------------------------------------------------------------------------
/.github/copilot-instructions.md:
--------------------------------------------------------------------------------
1 | # Project Instructions for AI Coding Tools
2 |
3 | This repository builds the QuantEcon Julia lectures using JupyterBook + MyST Markdown + MyST-NB execution.
4 | AI coding tools working in this repo should follow these guidelines for consistent formatting, structure, and execution.
5 |
6 | ------------------------------------------------------------------------------
7 |
8 | ## 1. Code Style and Formatting Conventions
9 |
10 | Follow the QuantEcon `style.md` guide strictly:
11 |
12 | - Use the conventions described in:
13 | https://github.com/QuantEcon/lecture-julia.myst/blob/main/style.md
14 | - Maintain consistent Julia formatting, including:
15 | - Non-mutating vs. mutating naming (`f` vs. `f!`)
16 | - Explicit `using` statements
17 | - Avoid global variables in notebooks
18 | - Reproducibility via fixed seeds
19 | - When editing MyST Markdown:
20 | - Use fenced code blocks with correct language identifiers
21 | - Do not mix Markdown and code execution in ambiguous ways
22 | - Preserve section structure, callouts, and MyST directives
23 | - Never use `begin` blocks for function definitions. Use either short-form or standard `function ... end` syntax.
24 | - Don't use `&&` when a conditional would be clearer. Prefer `if phi > remaining; continue;end` to `phi > remaining && continue`
25 |
26 | If unsure about style, imitate existing notebooks in `lectures/`.
27 |
28 | ------------------------------------------------------------------------------
29 |
30 | ## 2. Repository Structure Expectations
31 |
32 | Maintain the existing layout:
33 |
34 | lectures/
35 | topic_1/
36 | notebook_1.md
37 | notebook_2.md
38 | topic_2/
39 | notebook_3.md
40 | intro.md
41 | Manifest.toml
42 | Project.toml
43 | _config.yml
44 | _toc.yml
45 | style.md
46 | requirements.txt
47 |
48 |
49 | The requirements.txt file is for the jupyterbook dependencies, not the lecture notes themselves.
50 | Do not introduce new directory structures without explicit instruction.
51 |
52 | ------------------------------------------------------------------------------
53 |
54 | ## 3. Environment Setup for Notebook Execution
55 |
56 | AI tools may compile or test notebooks using the following:
57 |
58 | 1. Activate the Python environment:
59 |
60 | source .venv/bin/activate
61 |
62 | 2. Build the JupyterBook:
63 |
64 | jb build lectures
65 |
66 | 3. Inspect failures:
67 | The JupyterBook warnings will include file paths like:
68 |
69 | /path/to/notebook.md: WARNING: Executing notebook failed
70 | Reports saved in:
71 | lectures/_build/html/reports//.err.log
72 |
73 | AI suggestions should reference these logs when debugging notebook execution.
74 |
75 | To run Julia directly with the correct environment:
76 |
77 | ```
78 | julia --project=lectures
79 | ```
80 |
81 | Do not manually add in importing code for packages in a lecture (i.e., `import Pkg; Pkg.activate(joinpath(@__DIR__, ".."))` etc.) as it will be correctly activated by either jupyterbook or your activation of the julia environment with `julia --project=lectures`.
82 |
83 | ------------------------------------------------------------------------------
84 |
85 | ## 4. Expectations for Notebook Editing
86 |
87 | ### Julia Code Cells
88 | - Produce idiomatic, stable, predictable Julia.
89 | - Avoid unnecessary refactoring.
90 | - Use broadcasting, comprehensions, and vectorization when appropriate.
91 | - Prioritize clarity and reproducibility.
92 |
93 | ### MyST Notebook Cells
94 | - Preserve mystnb execution blocks.
95 | - Preserve input/output tags (e.g., hide-output, remove-input).
96 | - Maintain anchors, index directives, labels, and roles.
97 | - Do not introduce unsupported Jupyter features.
98 |
99 | ------------------------------------------------------------------------------
100 |
101 | ## 5. Documentation and Text Edits
102 |
103 | AI-generated text must:
104 | - Keep the pedagogical tone of existing QuantEcon lectures.
105 | - Use clean mathematical notation:
106 | - Inline math: $x_t = \\rho x_{t-1} + \\sigma \\varepsilon_t$
107 | - Display math: $$ ... $$
108 | - Prefer concise explanations and avoid verbosity.
109 |
110 | ------------------------------------------------------------------------------
111 |
112 | ## 6. Commit Behavior
113 |
114 | AI tools should:
115 | - Keep commits small and targeted.
116 | - Avoid mass rewrites.
117 | - Maintain full compatibility with the JupyterBook build.
118 |
119 | ------------------------------------------------------------------------------
120 |
121 | ## 7. Good Default Behaviors for AI Tools
122 |
123 | When uncertain:
124 | - Follow patterns already present in similar notebooks.
125 | - Test execution with `jb build lectures`.
126 | - Refer to the style guide.
127 | - Prefer conservative, minimally invasive edits.
128 | - Prioritize correctness of executed notebooks.
129 |
130 | ------------------------------------------------------------------------------
131 |
132 | ## 8. Allowed Tasks
133 |
134 | AI tools may:
135 | - Fix failing notebook cells.
136 | - Improve explanations, math, and MyST structure.
137 | - Propose small utility Julia functions.
138 | - Improve clarity or reproducibility.
139 |
140 | ------------------------------------------------------------------------------
141 |
142 | ## 9. Tasks to Avoid
143 |
144 | AI tools should not:
145 | - Change folder structure.
146 | - Modify `_config.yml` unless asked.
147 | - Convert markdown notebooks back to `.ipynb`.
148 | - Reorder large sections or rewrite whole lectures.
149 | - Add new dependencies without explicit instruction.
150 |
151 | ------------------------------------------------------------------------------
152 |
153 | ## 10. Reference Materials
154 |
155 | - Style guide:
156 | https://github.com/QuantEcon/lecture-julia.myst/blob/main/style.md
157 |
158 | - MyST-NB docs:
159 | https://myst-nb.readthedocs.io/
160 |
161 | - QuantEcon Julia documentation.
162 |
163 | ------------------------------------------------------------------------------
164 |
165 | These instructions apply to all AI coding assistants operating in this repository.
--------------------------------------------------------------------------------
/AGENTS.md:
--------------------------------------------------------------------------------
1 | # Project Instructions for AI Coding Tools
2 |
3 | This repository builds the QuantEcon Julia lectures using JupyterBook + MyST Markdown + MyST-NB execution.
4 | AI coding tools working in this repo should follow these guidelines for consistent formatting, structure, and execution.
5 |
6 | ------------------------------------------------------------------------------
7 |
8 | ## 1. Code Style and Formatting Conventions
9 |
10 | Follow the QuantEcon `style.md` guide strictly:
11 |
12 | - Use the conventions described in:
13 | https://github.com/QuantEcon/lecture-julia.myst/blob/main/style.md
14 | - Maintain consistent Julia formatting, including:
15 | - Non-mutating vs. mutating naming (`f` vs. `f!`)
16 | - Explicit `using` statements
17 | - Avoid global variables in notebooks
18 | - Reproducibility via fixed seeds
19 | - When editing MyST Markdown:
20 | - Use fenced code blocks with correct language identifiers
21 | - Do not mix Markdown and code execution in ambiguous ways
22 | - Preserve section structure, callouts, and MyST directives
23 | - Never use `begin` blocks for function definitions. Use either short-form or standard `function ... end` syntax.
24 | - Don't use `&&` when a conditional would be clearer. Prefer `if phi > remaining; continue;end` to `phi > remaining && continue`
25 |
26 | If unsure about style, imitate existing notebooks in `lectures/`.
27 |
28 | ------------------------------------------------------------------------------
29 |
30 | ## 2. Repository Structure Expectations
31 |
32 | Maintain the existing layout:
33 |
34 | lectures/
35 | topic_1/
36 | notebook_1.md
37 | notebook_2.md
38 | topic_2/
39 | notebook_3.md
40 | intro.md
41 | Manifest.toml
42 | Project.toml
43 | _config.yml
44 | _toc.yml
45 | style.md
46 | requirements.txt
47 |
48 |
49 | The requirements.txt file is for the jupyterbook dependencies, not the lecture notes themselves.
50 | Do not introduce new directory structures without explicit instruction.
51 |
52 | ------------------------------------------------------------------------------
53 |
54 | ## 3. Environment Setup for Notebook Execution
55 |
56 | AI tools may compile or test notebooks using the following:
57 |
58 | 1. Activate the Python environment:
59 |
60 | source .venv/bin/activate
61 |
62 | 2. Build the JupyterBook:
63 |
64 | jb build lectures
65 |
66 | 3. Inspect failures:
67 | The JupyterBook warnings will include file paths like:
68 |
69 | /path/to/notebook.md: WARNING: Executing notebook failed
70 | Reports saved in:
71 | lectures/_build/html/reports//.err.log
72 |
73 | AI suggestions should reference these logs when debugging notebook execution.
74 |
75 | To run Julia directly with the correct environment:
76 |
77 | ```
78 | julia --project=lectures
79 | ```
80 |
81 | Do not manually add in importing code for packages in a lecture (i.e., `import Pkg; Pkg.activate(joinpath(@__DIR__, ".."))` etc.) as it will be correctly activated by either jupyterbook or your activation of the julia environment with `julia --project=lectures`.
82 |
83 | ------------------------------------------------------------------------------
84 |
85 | ## 4. Expectations for Notebook Editing
86 |
87 | ### Julia Code Cells
88 | - Produce idiomatic, stable, predictable Julia.
89 | - Avoid unnecessary refactoring.
90 | - Use broadcasting, comprehensions, and vectorization when appropriate.
91 | - Prioritize clarity and reproducibility.
92 |
93 | ### MyST Notebook Cells
94 | - Preserve mystnb execution blocks.
95 | - Preserve input/output tags (e.g., hide-output, remove-input).
96 | - Maintain anchors, index directives, labels, and roles.
97 | - Do not introduce unsupported Jupyter features.
98 |
99 | ------------------------------------------------------------------------------
100 |
101 | ## 5. Documentation and Text Edits
102 |
103 | AI-generated text must:
104 | - Keep the pedagogical tone of existing QuantEcon lectures.
105 | - Use clean mathematical notation:
106 | - Inline math: $x_t = \\rho x_{t-1} + \\sigma \\varepsilon_t$
107 | - Display math: $$ ... $$
108 | - Prefer concise explanations and avoid verbosity.
109 |
110 | ------------------------------------------------------------------------------
111 |
112 | ## 6. Commit Behavior
113 |
114 | AI tools should:
115 | - Keep commits small and targeted.
116 | - Avoid mass rewrites.
117 | - Maintain full compatibility with the JupyterBook build.
118 |
119 | ------------------------------------------------------------------------------
120 |
121 | ## 7. Good Default Behaviors for AI Tools
122 |
123 | When uncertain:
124 | - Follow patterns already present in similar notebooks.
125 | - Test execution with `jb build lectures`.
126 | - Activate with `.venv` first if it exists.
127 | - Refer to the style guide.
128 | - Prefer conservative, minimally invasive edits.
129 | - Prioritize correctness of executed notebooks.
130 |
131 | ------------------------------------------------------------------------------
132 |
133 | ## 8. Allowed Tasks
134 |
135 | AI tools may:
136 | - Fix failing notebook cells.
137 | - Improve explanations, math, and MyST structure.
138 | - Propose small utility Julia functions.
139 | - Improve clarity or reproducibility.
140 |
141 | ------------------------------------------------------------------------------
142 |
143 | ## 9. Tasks to Avoid
144 |
145 | AI tools should not:
146 | - Change folder structure.
147 | - Modify `_config.yml` unless asked.
148 | - Convert markdown notebooks back to `.ipynb`.
149 | - Reorder large sections or rewrite whole lectures.
150 | - Add new dependencies without explicit instruction.
151 |
152 | ------------------------------------------------------------------------------
153 |
154 | ## 10. Reference Materials
155 |
156 | - Style guide:
157 | https://github.com/QuantEcon/lecture-julia.myst/blob/main/style.md
158 |
159 | - MyST-NB docs:
160 | https://myst-nb.readthedocs.io/
161 |
162 | - QuantEcon Julia documentation.
163 |
164 | ------------------------------------------------------------------------------
165 |
166 | These instructions apply to all AI coding assistants operating in this repository.
--------------------------------------------------------------------------------
/lectures/more_julia/data_statistical_packages.md:
--------------------------------------------------------------------------------
1 | ---
2 | jupytext:
3 | text_representation:
4 | extension: .md
5 | format_name: myst
6 | kernelspec:
7 | display_name: Julia
8 | language: julia
9 | name: julia-1.12
10 | ---
11 |
12 | (data_statistical_packages)=
13 | ```{raw} html
14 |
19 | ```
20 |
21 | # General, Data, and Statistics Packages
22 |
23 | ```{contents} Contents
24 | :depth: 2
25 | ```
26 |
27 | ## Overview
28 |
29 | This lecture explores some of the key packages for working with data and doing statistics in Julia.
30 |
31 | In particular, we will examine the `DataFrame` object in detail (i.e., construction, manipulation, querying, visualization, and nuances like missing data).
32 |
33 | While Julia is not an ideal language for pure cookie-cutter statistical analysis, it has many useful packages to provide those tools as part of a more general solution.
34 |
35 | This list is not exhaustive, and others can be found in organizations such as [JuliaStats](https://github.com/JuliaStats), [JuliaData](https://github.com/JuliaData/), and [QueryVerse](https://github.com/queryverse).
36 |
37 |
38 | ```{code-cell} julia
39 | ---
40 | tags: [hide-output]
41 | ---
42 | using LinearAlgebra, Statistics, DataFrames
43 | ```
44 |
45 | ## DataFrames
46 |
47 | A useful package for working with data is [DataFrames.jl](https://github.com/JuliaStats/DataFrames.jl).
48 |
49 | The most important data type provided is a `DataFrame`, a two dimensional array for storing heterogeneous data.
50 |
51 | Although data can be heterogeneous within a `DataFrame`, the contents of the columns must be homogeneous
52 | (of the same type).
53 |
54 | This is analogous to a `data.frame` in R, a `DataFrame` in Pandas (Python) or, more loosely, a spreadsheet in Excel.
55 |
56 | There are a few different ways to create a DataFrame.
57 |
58 | ### Constructing and Accessing a DataFrame
59 |
60 | The first is to set up columns and construct a dataframe by assigning names
61 |
62 | ```{code-cell} julia
63 | using DataFrames
64 |
65 | # note use of missing
66 | commodities = ["crude", "gas", "gold", "silver"]
67 | last_price = [4.2, 11.3, 12.1, missing]
68 | df = DataFrame(commod = commodities, price = last_price)
69 | ```
70 |
71 | Columns of the `DataFrame` can be accessed by name using `df.col`, as below
72 |
73 | ```{code-cell} julia
74 | df.price
75 | ```
76 |
77 | Note that the type of this array has values `Union{Missing, Float64}` since it was created with a `missing` value.
78 |
79 | ```{code-cell} julia
80 | df.commod
81 | ```
82 |
83 | The `DataFrames.jl` package provides a number of methods for acting on `DataFrame`'s, such as `describe`.
84 |
85 | ```{code-cell} julia
86 | DataFrames.describe(df)
87 | ```
88 |
89 | While often data will be generated all at once, or read from a file, you can add to a `DataFrame` by providing the key parameters.
90 |
91 | ```{code-cell} julia
92 | nt = (commod = "nickel", price = 5.1)
93 | push!(df, nt)
94 | ```
95 |
96 | Named tuples can also be used to construct a `DataFrame`, and have it properly deduce all types.
97 |
98 | ```{code-cell} julia
99 | nt = (t = 1, col1 = 3.0)
100 | df2 = DataFrame([nt])
101 | push!(df2, (t = 2, col1 = 4.0))
102 | ```
103 |
104 | In order to modify a column, access the mutating version by the symbol `df[!, :col]`.
105 |
106 | ```{code-cell} julia
107 | df[!, :price]
108 | ```
109 |
110 | Which allows modifications, like other mutating `!` functions in julia.
111 |
112 | ```{code-cell} julia
113 | df[!, :price] *= 2.0 # double prices
114 | ```
115 |
116 | As discussed in the next section, note that the {ref}`fundamental types `, is propagated, i.e. `missing * 2 === missing`.
117 |
118 | ### Working with Missing
119 |
120 | As we discussed in {ref}`fundamental types `, the semantics of `missing` are that mathematical operations will not silently ignore it.
121 |
122 | In order to allow `missing` in a column, you can create/load the `DataFrame`
123 | from a source with `missing`'s, or call `allowmissing!` on a column.
124 |
125 | ```{code-cell} julia
126 | allowmissing!(df2, :col1) # necessary to add in a for col1
127 | push!(df2, (t = 3, col1 = missing))
128 | push!(df2, (t = 4, col1 = 5.1))
129 | ```
130 |
131 | We can see the propagation of `missing` to caller functions, as well as a way to efficiently calculate with non-missing data.
132 |
133 | ```{code-cell} julia
134 | @show mean(df2.col1)
135 | @show mean(skipmissing(df2.col1))
136 | ```
137 |
138 | And to replace the `missing`
139 |
140 | ```{code-cell} julia
141 | df2.col1 .= coalesce.(df2.col1, 0.0) # replace all missing with 0.0
142 | ```
143 |
144 | ### Manipulating and Transforming DataFrames
145 |
146 | One way to do an additional calculation with a `DataFrame` is to use the `@transform` macro from `DataFramesMeta.jl`.
147 |
148 | The following are code only blocks, which would require installation of the packages in a separate environment.
149 |
150 | ```{code-block} julia
151 | using DataFramesMeta
152 | f(x) = x^2
153 | df2 = @transform(df2, :col2=f.(:col1))
154 | ```
155 |
156 | ### Categorical Data
157 |
158 | For data that is [categorical](https://juliadata.github.io/DataFrames.jl/stable/man/categorical/)
159 |
160 | ```{code-block} julia
161 | using CategoricalArrays
162 | id = [1, 2, 3, 4]
163 | y = ["old", "young", "young", "old"]
164 | y = CategoricalArray(y)
165 | df = DataFrame(id = id, y = y)
166 | ```
167 |
168 | ```{code-block} julia
169 | levels(df.y)
170 | ```
171 |
172 | ### Visualization, Querying, and Plots
173 |
174 | The `DataFrame` (and similar types that fulfill a standard generic interface) can fit into a variety of packages.
175 |
176 | One set of them is the [QueryVerse](https://github.com/queryverse).
177 |
178 | **Note:** The QueryVerse, in the same spirit as R's tidyverse, makes heavy use of the pipeline syntax `|>`.
179 |
180 | ## Statistics and Econometrics
181 |
182 | While Julia is not intended as a replacement for R, Stata, and similar specialty languages, it has a growing number of packages aimed at statistics and econometrics.
183 |
184 | Many of the packages live in the [JuliaStats organization](https://github.com/JuliaStats/).
185 |
186 | A few to point out
187 |
188 | * [StatsBase](https://github.com/JuliaStats/StatsBase.jl) has basic statistical functions such as geometric and harmonic means, auto-correlations, robust statistics, etc.
189 | * [StatsFuns](https://github.com/JuliaStats/StatsFuns.jl) has a variety of mathematical functions and constants such as pdf and cdf of many distributions, softmax, etc.
190 |
191 | ### General Linear Models
192 |
193 | To run linear regressions and similar statistics, use the [GLM](http://juliastats.github.io/GLM.jl/latest/) package.
194 |
195 | ```{code-block} julia
196 | using GLM
197 |
198 | x = randn(100)
199 | y = 0.9 .* x + 0.5 * rand(100)
200 | df = DataFrame(x = x, y = y)
201 | ols = lm(@formula(y~x), df) # R-style notation
202 | ```
203 |
204 | To display the results in a useful tables for LaTeX and the REPL, use
205 | [RegressionTables](https://github.com/jmboehm/RegressionTables.jl/) for output
206 | similar to the Stata package esttab and the R package stargazer.
207 |
208 | ```{code-block} julia
209 | using RegressionTables
210 | regtable(ols)
211 | # regtable(ols, renderSettings = latexOutput()) # for LaTex output
212 | ```
--------------------------------------------------------------------------------
/lectures/multi_agent_models/schelling.md:
--------------------------------------------------------------------------------
1 | ---
2 | jupytext:
3 | text_representation:
4 | extension: .md
5 | format_name: myst
6 | kernelspec:
7 | display_name: Julia
8 | language: julia
9 | name: julia-1.12
10 | ---
11 | (schelling)=
12 | ```{raw} html
13 |
18 | ```
19 |
20 | # Schelling's Segregation Model
21 |
22 | ```{index} single: Schelling Segregation Model
23 | ```
24 |
25 | ```{index} single: Models; Schelling's Segregation Model
26 | ```
27 |
28 | ```{contents} Contents
29 | :depth: 2
30 | ```
31 |
32 | ## Overview
33 |
34 | In 1969, Thomas C. Schelling developed a simple but striking model of racial segregation {cite}`Schelling1969`.
35 |
36 | His model studies the dynamics of racially mixed neighborhoods.
37 |
38 | Like much of Schelling's work, the model shows how local interactions can lead to surprising aggregate structure.
39 |
40 | In particular, it shows that relatively mild preference for neighbors of similar race can lead in aggregate to the collapse of mixed neighborhoods, and high levels of segregation.
41 |
42 | In recognition of this and other research, Schelling was awarded the 2005 Nobel Prize in Economic Sciences (joint with Robert Aumann).
43 |
44 | In this lecture we (in fact you) will build and run a version of Schelling's model.
45 |
46 | ## The Model
47 |
48 | We will cover a variation of Schelling's model that is easy to program and captures the main idea.
49 |
50 | Suppose we have two types of people: orange people and green people.
51 |
52 | For the purpose of this lecture, we will assume there are 250 of each type.
53 |
54 | These agents all live on a single unit square.
55 |
56 | The location of an agent is just a point $(x, y)$, where $0 < x, y < 1$.
57 |
58 | ### Preferences
59 |
60 | We will say that an agent is *happy* if half or more of her 10 nearest neighbors are of the same type.
61 |
62 | Here 'nearest' is in terms of [Euclidean distance](https://en.wikipedia.org/wiki/Euclidean_distance).
63 |
64 | An agent who is not happy is called *unhappy*.
65 |
66 | An important point here is that agents are not averse to living in mixed areas.
67 |
68 | They are perfectly happy if half their neighbors are of the other color.
69 |
70 | ### Behavior
71 |
72 | Initially, agents are mixed together (integrated).
73 |
74 | In particular, the initial location of each agent is an independent draw from a bivariate uniform distribution on $S = (0, 1)^2$.
75 |
76 | Now, cycling through the set of all agents, each agent is now given the chance to stay or move.
77 |
78 | We assume that each agent will stay put if they are happy and move if unhappy.
79 |
80 | The algorithm for moving is as follows
81 |
82 | 1. Draw a random location in $S$
83 | 1. If happy at new location, move there
84 | 1. Else, go to step 1
85 |
86 | In this way, we cycle continuously through the agents, moving as required.
87 |
88 | We continue to cycle until no one wishes to move.
89 |
90 | ## Results
91 |
92 | Let's have a look at the results we got when we coded and ran this model.
93 |
94 | As discussed above, agents are initially mixed randomly together
95 |
96 | ```{figure} /_static/figures/schelling_fig1.png
97 |
98 | ```
99 |
100 | But after several cycles they become segregated into distinct regions
101 |
102 | ```{figure} /_static/figures/schelling_fig2.png
103 |
104 | ```
105 |
106 | ```{figure} /_static/figures/schelling_fig3.png
107 |
108 | ```
109 |
110 | ```{figure} /_static/figures/schelling_fig4.png
111 |
112 | ```
113 |
114 | In this instance, the program terminated after 4 cycles through the set of
115 | agents, indicating that all agents had reached a state of happiness.
116 |
117 | What is striking about the pictures is how rapidly racial integration breaks down.
118 |
119 | This is despite the fact that people in the model don't actually mind living mixed with the other type.
120 |
121 | Even with these preferences, the outcome is a high degree of segregation.
122 |
123 | ## Exercises
124 |
125 | (schelling_ex1)=
126 | ### Exercise 1
127 |
128 | Implement and run this simulation for yourself.
129 |
130 | Use 250 agents of each type.
131 |
132 | ## Solutions
133 |
134 | ### Exercise 1
135 |
136 | Here's one solution that does the job we want. If you feel like a
137 | further exercise you can probably speed up some of the computations and
138 | then increase the number of agents.
139 |
140 |
141 |
142 | ```{code-cell} julia
143 | ---
144 | tags: [remove-cell]
145 | ---
146 | using Test, Random
147 | ```
148 |
149 | ```{code-cell} julia
150 | using Plots, LinearAlgebra, Statistics
151 |
152 | ```
153 |
154 | ```{code-cell} julia
155 | ---
156 | tags: [remove-cell]
157 | ---
158 | Random.seed!(42);
159 | ```
160 |
161 | ```{code-cell} julia
162 | Agent(; kind, location = rand(2)) = (; kind, location)
163 |
164 | draw_location!(a) = a.location .= rand(2)
165 |
166 | # distance is just 2 norm: uses our subtraction function
167 | get_distance(a, agent) = norm(a.location - agent.location)
168 |
169 | function is_happy(a)
170 | distances = [(get_distance(a, agent), agent) for agent in agents]
171 | sort!(distances)
172 | neighbors = [agent for (d, agent) in distances[1:neighborhood_size]]
173 | share = mean(isequal(a.kind), other.kind for other in neighbors)
174 |
175 | # can also do
176 | # share = mean(isequal(a.kind),
177 | # first(agents[idx]) for idx in
178 | # partialsortperm(get_distance.(Ref(a), agents),
179 | # 1:neighborhood_size))
180 |
181 | return share >= preference
182 | end
183 |
184 | function update!(a)
185 | # If not happy, then randomly choose new locations until happy.
186 | while !is_happy(a)
187 | draw_location!(a)
188 | end
189 | end
190 |
191 | function plot_distribution(agents)
192 | x_vals_0, y_vals_0 = zeros(0), zeros(0)
193 | x_vals_1, y_vals_1 = zeros(0), zeros(0)
194 |
195 | # obtain locations of each type
196 | for agent in agents
197 | x, y = agent.location
198 | if agent.kind == 0
199 | push!(x_vals_0, x)
200 | push!(y_vals_0, y)
201 | else
202 | push!(x_vals_1, x)
203 | push!(y_vals_1, y)
204 | end
205 | end
206 |
207 | p = scatter(x_vals_0, y_vals_0, color = :orange, markersize = 8,
208 | alpha = 0.6)
209 | scatter!(x_vals_1, y_vals_1, color = :green, markersize = 8, alpha = 0.6)
210 | return plot!(legend = :none)
211 | end
212 | ```
213 |
214 | ```{code-cell} julia
215 | num_of_type_0 = 250
216 | num_of_type_1 = 250
217 | neighborhood_size = 10 # Number of agents regarded as neighbors
218 | preference = 0.5 # Want their kind to make at least this share of the neighborhood
219 |
220 | # Create a list of agents
221 | agents = vcat([Agent(kind = 0) for i in 1:num_of_type_0],
222 | [Agent(kind = 1) for i in 1:num_of_type_1])
223 |
224 | plot_array = Any[]
225 |
226 | # loop until none wishes to move
227 | while true
228 | push!(plot_array, plot_distribution(agents))
229 | no_one_moved = true
230 | for agent in agents
231 | old_location = copy(agent.location)
232 | update!(agent)
233 | if norm(old_location - agent.location) ≉ 0
234 | no_one_moved = false
235 | end
236 | end
237 | if no_one_moved
238 | break
239 | end
240 | end
241 | n = length(plot_array)
242 | plot(plot_array...,
243 | layout = (n, 1),
244 | size = (600, 400n),
245 | title = reshape(["Cycle $i" for i in 1:n], 1, n))
246 | ```
247 |
248 | ```{code-cell} julia
249 | ---
250 | tags: [remove-cell]
251 | ---
252 | @test sum(agent.kind for agent in agents) == 250
253 | ```
254 |
255 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # lecture-julia.myst
2 |
3 | Source for julia.quantecon.org and notebooks in https://github.com/QuantEcon/lecture-julia.notebooks
4 |
5 | To contribute, you can use GitHub's online editor for small changes, and do a full local installation for large ones.
6 |
7 | See https://github.com/QuantEcon/lecture-julia.myst/blob/main/style.md for some basic coding standards.
8 |
9 | ## Online Editor
10 |
11 | On this website hit `.` to enter into the web editor. From this, you can submit suggested patches and fix typos. This will help you create a [pull request](https://quantecon.github.io/lecture-julia.myst/software_engineering/version_control.html#collaboration-via-pull-request) for maintainers here to examine.
12 |
13 | ## Local Development
14 |
15 | It is straightforward to install the Jupyter Book and Julia software necessary for more significant changes. For Windows support, it is best to use WSL. See `[WSL Setup Instructions](./wsl.md)` for more details.
16 |
17 | ### Setup
18 |
19 | 1. [Install Julia, Conda, and VS Code](https://quantecon.github.io/lecture-julia.myst/getting_started_julia/getting_started.html) following the documentation for using these notes.
20 | 2. Modify [VS Code settings](https://quantecon.github.io/lecture-julia.myst/software_engineering/tools_editors.html#optional-extensions-and-settings) and consider [additional extensions](https://quantecon.github.io/lecture-julia.myst/software_engineering/tools_editors.html#optional-extensions). Some others to consider are the [MyST-Markdown](https://github.com/executablebooks/myst-vs-code) and [Spell Checking](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) extensions. You will also likely want the Python and Jupyter extensions installed
21 | 3. Ensure that [Git](https://quantecon.github.io/lecture-julia.myst/software_engineering/version_control.html#setup) is set up correctly. In particular, this ensures that Windows users use the Linux end-of-line characters.
22 | 4. Clone this repository (in VS Code, you can use `` then `Clone` then `Clone from GitHub` then choose the repo as `https://github.com/QuantEcon/lecture-julia.myst`).
23 |
24 | 6. Open this repository in VS Code. If you cloned in a separate terminal, navigate to the directory and type `code .`
25 |
26 | 7. Start a VS Code terminal with ```` or through any other method. Create a conda environment.
27 |
28 | ```bash
29 | conda create -n lecture-julia.myst python=3.11
30 | conda activate lecture-julia.myst
31 | pip install -r requirements.txt
32 | ```
33 |
34 | This will install all the Jupyter Book packages required to edit and build the lectures.
35 |
36 | 8. Set the default interpreter for VS Code's Python extension to be the conda environment
37 | - Press `` then `Python: Select Interpreter`.
38 | - Choose the interpreter with `lecture-julia.myst` which should now be automatically activated in the terminal.
39 | - If the interpreter does not show up in the drop-down, close and reopen VS Code, then try again. Alternatively, you can run this step at the end of the setup process.
40 | - Whenever reopening VS Code, re-run `conda activate lecture-julia.myst` to ensure the environment remains active.
41 | 9. Ensure that IJulia is installed for the main Julia environment
42 | - Ensure you have the conda environment activated with `conda activate lecture-julia.myst`
43 | - To do this, run `julia` in the terminal and then `] add IJulia` in the Julia REPL. You will want to do this in the main environment and not the `lectures` environment, as used below.
44 | 10. Install the Julia packages required for the lecture notes.
45 |
46 | ```bash
47 | julia --project=lectures --threads auto -e 'using Pkg; Pkg.instantiate();'
48 | ```
49 |
50 |
51 | **(Optional) REPL Integration**
52 | With [MyST-Markdown](https://github.com/executablebooks/myst-vs-code) and [Julia](https://marketplace.visualstudio.com/items?itemName=julialang.language-julia) installed, you can ensure that pressing `` on lines of code are sent to a Julia REPL.
53 | 1. Open Key Bindings with ``.
54 | 2. Search for the `Julia: Send Current Line or Selection to REPL` binding.
55 | 3. Right Click on the key binding with `juliamarkdown` on it, and choose `Change When Expression`, and change `juliamarkdown` to just `markdown`.
56 |
57 |
58 | ## Executing Code in Markdown Files
59 | If you installed the REPL Integration above, then in a `.md` file,
60 |
61 | 1. Start a Julia REPL with `> Julia: Start REPL`.
62 | 2. Activate the project file in the REPL with `] activate lectures`.
63 | 3. Then, assuming that you set up the keybindings above, you can send a line of code in the markdown to the REPL with ``.
64 |
65 | Code can be executed line by line, or you can select a chunk of code and execute it.
66 |
67 | ## Executing Intermediate Code in Jupyter Notebooks
68 | From a built jupyterbook, you can navigate to the `.ipynb` used for the generation. The files are located in `lectures/_build/jupyter_execute/dynamic_programming/mccall_model.ipynb` etc.
69 |
70 | There are two options:
71 |
72 | 1. With the Julia vscode extension installed, open the file and run code cells.
73 | - The formatting will be incorrect, but the code will be.
74 | - The first time you run this you may need to choose the kernel. Assuming you installed with juliaup, you should be able to choose `Julia` as the kernel and the juliaup installed julia version
75 | - This will automatically activate the appropriate project and manifest file.
76 | 2. With your conda environment activated, go `cd lectures` then `jupyter lab`
77 | - Navigate to the files in jupyter itself. Because you ran this in the environment with the `Project.toml` and `Manifest.toml` files, the environment should be activated correctly.
78 | - If you have any issues, it is likely that you need to activate the environment in the terminal, or that you have note done the `] add IJulia` step from a julia REPL (whihc must be done in the default environment, i.e. not activated in `lectures`).
79 |
80 | ## Example Operations
81 | ### Building the lectures
82 | To do a full build of the lectures:
83 |
84 | ```bash
85 | jupyter-book build lectures
86 | ```
87 |
88 | or
89 |
90 | ```bash
91 | jb build lectures
92 | ```
93 |
94 | This will take a while. But it will populate your cache, so future iteration is faster.
95 |
106 |
107 | ### Cleaning Lectures
108 | To clean up (i.e., delete the build)
109 |
110 | ```bash
111 | jupyter-book clean lectures
112 | ```
113 |
114 | or
115 |
116 | ```bash
117 | jb clean lectures
118 | ```
119 |
120 | and to clean the `execution` cache you can use
121 |
122 | ```bash
123 | jb clean lectures --all
124 | ```
125 | ### Debugging Generated Content
126 |
127 | After execution, you can find the generated `.ipynb` and `.jl` files in `_build/jupyter_execute` for each lecture.
128 | - To see errors, you can open these in JupyterLab, the Jupyter support within VS Code, etc.
129 | - If using the Julia REPL in VS Code, make sure to do `] activate lectures` prior to testing to ensure the packages are activated. This is not necessary when opening in Jupyter.
130 |
131 | ## Formatting code
132 | Julia code blocks in the myst `.md` files can be formatted using a script in this folder. To manually do so, insure you have the `] add JuliaFormatter` within your default julia environment, then call on the commandline like
133 |
134 | ```bash
135 | julia format_myst.jl lectures/getting_started_julia/getting_started.md
136 | ```
137 |
138 | As a helper, you can call a shell script to do it for an entire folder
139 |
140 | ```bash
141 | bash format_all_directory.sh lectures/dynamic_programming
142 | ```
143 |
144 | or to also do the unicode substitutions
145 |
146 | ```bash
147 | bash format_all_directory.sh lectures/dynamic_programming true
148 | ```
--------------------------------------------------------------------------------
/prompts/differentiation.md:
--------------------------------------------------------------------------------
1 | # Instructions for Differentiable Code
2 | In general write clean code without worrying about small performance changes. However, in some cases we need to maintain strict control over memory allocations, especially if I mention you should use Enzyme.
3 |
4 | In that case, you are an expert Julia developer specializing in high-performance computing and zero-allocation patterns. When writing code, prioritize strict memory management and in-place operations. Adhere to the following guidelines`:
5 |
6 | Our main target will be Enzyme.jl and occasionally ForwardDiff.jl.
7 |
8 | ## Enzyme.jl Guidelines
9 | - See https://enzymead.github.io/Enzyme.jl/dev/ for enzyme documentation
10 | - In cases when you need to write custom rules, EnzymeTestUtils provides a way to test against FiniteDiff automatically.
11 | - See https://enzymead.github.io/Enzyme.jl/dev/api/#EnzymeTestUtils.test_forward-Tuple%7BAny,%20Any,%20Vararg%7BAny%7D%7D
12 | - https://enzymead.github.io/Enzyme.jl/dev/api/#EnzymeTestUtils.test_reverse-Tuple{Any,%20Any,%20Vararg{Any}}
13 | - You need to write inplace code without allocations. See `Inplace Coding Guidelines` below
14 | - Functions should be written to be type-stable
15 | - You will need to preallocate any buffers and pass as arguments.
16 |
17 | ## Enzyme & Buffer Conventions
18 | When writing the Enzyme Differentiable Julia code, adhere to these SciML/Enzyme patterns:
19 |
20 | 1. **Function Signature:** `function name!(out, inputs..., params, cache)`. Place the `cache` (workspace) argument last.
21 | 2. **Cache Structs:** Do not pass individual arrays for buffers. Create a `struct NameCache` to hold all pre-allocated temporary arrays.
22 | 3. **Enzyme Compatibility:** * Ensure the code is compatible with `Enzyme.autodiff`.
23 | * Assume the user will pass `Duplicated(cache, d_cache)` for the workspace.
24 | * The `cache` struct must contain mutable fields (Arrays) that match the precision of the inputs.
25 | 4. **No Internal Allocation:** Strictly use the fields in `cache` for all intermediate vector/matrix operations.
26 | 5. **Use make_zero**: Use `Enzyme.make_zero(x)` to create shadow copies for gradients of inputs/outputs/cache rather than manual allocation.
27 | 6. **Enzyme Assignment Loops** Sometimes Enzyme hits an Activity Analysis issues with assignment, for example instad of `x[:,1] .= x_0` or equivalent things with view, it needs. In that case you can use manual loop for assignment, but put a comment to explain why
28 | ```julia
29 | # Enzyme has challenges with activity analysis on broadcasting assignments
30 | @inbounds for i in 1:N
31 | x[i, 1] = x_0[i]
32 | end
33 | ```
34 |
35 |
36 | Follow the coding pattern in this example, for example.
37 | ```
38 | using Enzyme, LinearAlgebra
39 |
40 | # 1. Define the Cache Struct
41 | struct SimCache{T}
42 | tmp_vec::Vector{T}
43 | tmp_mat::Matrix{T}
44 | end
45 |
46 | # Helper to build it (good for users)
47 | alloc_cache(n) = SimCache(zeros(n), zeros(n, n))
48 |
49 | # 2. The In-Place Function
50 | # Order: out, x (input), cache (buffers)
51 | function simulate!(out, x, cache::SimCache)
52 | # unpack for clarity
53 | tmp = cache.tmp_vec
54 |
55 | # Example: Intermediate computation that needs a buffer
56 | # If we didn't have cache, this line would allocate
57 | @. tmp = x * x + 2
58 |
59 | # Write to out
60 | @. out = tmp^2
61 | return nothing
62 | end
63 |
64 | # 3. Setup for Enzyme
65 | n = 100
66 | x = rand(n)
67 | out = zeros(n)
68 | cache = alloc_cache(n)
69 |
70 | # Create "Shadows" (gradients)
71 | # Enzyme.make_zero creates a structural copy with all zeros
72 | dx = Enzyme.make_zero(x)
73 | dout = Enzyme.make_zero(out) # "Seed" for the gradient (e.g., set to 1s if scalar)
74 | dcache = Enzyme.make_zero(cache) # The shadow workspace!
75 |
76 | # Initialize the seed (e.g., we want gradient of sum(out))
77 | dout .= 1.0
78 |
79 | # 4. The Call
80 | # Note: We pass Duplicated for the cache because it is MUTATED.
81 | autodiff(Reverse, simulate!,
82 | Duplicated(out, dout),
83 | Duplicated(x, dx),
84 | Duplicated(cache, dcache)
85 | )
86 | ```
87 |
88 | ### Testing to ensure Type Safety and No Allocations
89 | - For any Enzyme-differentiable function, you should add asserts during development to ensure type stability and no allocations.
90 | - With the `Test` package, you can use `@inferred` to check type stability and `@allocated` to check allocations.
91 |
92 | For example:
93 |
94 | ```julia
95 | using Test
96 |
97 | function stable_func(x)
98 | return x * 2.0
99 | end
100 |
101 | function unstable_func(x)
102 | # Returns Int if x > 0, Float64 otherwise (Type Unstable!)
103 | x > 0 ? 1 : 1.0
104 | end
105 |
106 | @testset "Type Stability" begin
107 | x = 1.0
108 |
109 | # PASSES: Compiler infers Float64, actual is Float64
110 | @inferred stable_func(x)
111 |
112 | # FAILS: Compiler infers Union{Float64, Int64}, actual is one of them
113 | # Throws: "return type Union{Float64, Int64} does not match inferred type..."
114 | @inferred unstable_func(x)
115 | end
116 | function compute!(out, x)
117 | # Example: Allocation-free operation
118 | out .= x .* 2
119 | return nothing
120 | end
121 |
122 | @testset "Allocations" begin
123 | out = zeros(10)
124 | x = rand(10)
125 |
126 | # 1. WARMUP: Run once to force compilation
127 | compute!(out, x)
128 |
129 | # 2. ASSERT: Check allocations are exactly 0
130 | # Note: We interpolate arguments ($) inside benchmark tools,
131 | # but strictly speaking @allocated just runs the expression.
132 | allocs = @allocated compute!(out, x)
133 |
134 | @test allocs == 0
135 | end
136 | ```
137 |
138 |
139 | ### Testing with Finite Differences
140 | In cases where a custom rule is required, or there is a concern that gradients may be incorrect, use EnzymeTestUtils to compare against finite differences. Follow this example, which extends the above code.
141 |
142 | Even if you only care about the gradient of `x`, you **must** mark the `out` and `cache` arguments as `Duplicated` because they are mutated.
143 |
144 | **Example: Testing Reverse Mode**
145 | ```julia
146 | using Enzyme, EnzymeTestUtils, Test
147 |
148 | # 1. Setup Data
149 | x = randn(10)
150 | out = zeros(10)
151 | cache = alloc_cache(10) # User-defined helper to build cache struct
152 |
153 | # 2. Test Gradient of `x`
154 | # We use `test_reverse` to compare AD against Finite Differences.
155 | # Note: `out` and `cache` are mutated, so they MUST be Duplicated.
156 | test_reverse(simulate!, Const,
157 | (out, Duplicated), # Mutated Output
158 | (x, Duplicated), # Input (Active for differentiation)
159 | (cache, Duplicated) # Mutated Workspace
160 | )
161 | # Test Tangent of `x`
162 | test_forward(simulate!, Const,
163 | (out, Duplicated),
164 | (x, Duplicated),
165 | (cache, Duplicated)
166 | )
167 | ```
168 |
169 | # Inplace Coding Guidelines
170 |
171 | In that case, you are an expert Julia developer specializing in high-performance computing and zero-allocation patterns. When writing code, prioritize strict memory management and in-place operations. Adhere to the following guidelines:
172 |
173 | ### 1. Matrix Multiplication (`mul!`)
174 | Avoid `*` for matrix operations when a destination buffer exists. Use `LinearAlgebra.mul!`.
175 | - **Matrix-Matrix:** `mul!(C, A, B)` computes $C = AB$ overwriting $C$.
176 | - **Matrix-Vector:** `mul!(y, A, x)` computes $y = Ax$ overwriting $y$.
177 | - **5-Argument Interface:** Use `mul!(Y, A, B, \alpha, \beta)` to compute $Y = \alpha AB + \beta Y$. This is a "muladd" operation that avoids allocating a temporary buffer for $AB$ before adding it to $Y$.
178 |
179 | ### 2. In-Place Linear Solves (`ldiv!`)
180 | Avoid `\` (backslash) inside hot loops.
181 | - Pre-factorize matrices (e.g., LU, Cholesky) outside the loop: `F = lu(A)` or `F = cholesky(A)`.
182 | - Use `ldiv!(F, b)` to solve $Ax=b$ in-place, overwriting vector `b` with the solution.
183 | - Use `ldiv!(y, F, x)` if you need to keep `x` intact and write the solution to `y`.
184 |
185 | ### 3. Quadratic Forms (`dot`)
186 | Avoid `x' * A * x` or `(x' * A) * y`. These create temporary vector allocations.
187 | - Use the 3-argument dot product: `dot(x, A, y)` computes $x^T A y$ without allocating the intermediate vector $Ay$.
188 | - For quadratic forms $x^T A x$, use `dot(x, A, x)`.
189 |
190 | ### 4. Symmetrization (Kalman Filters/Covariances)
191 | In algorithms like Kalman filtering, numerical errors destroy symmetry.
192 | - **Preferred:** Wrap the matrix in `Symmetric(A)` or `Hermitian(A)` rather than forcing data movement.
193 | - **In-Place Enforcement:** If you must materialize the symmetric matrix (e.g., before a LAPACK call that accesses the full matrix), calculate one triangle and copy it to the other using `LinearAlgebra.copytri!(A, 'U')` (copies Upper to Lower) or `'L'` (Lower to Upper).
194 | - **Averaging:** If you specifically need $A \leftarrow (A + A^T)/2$ to average errors, use an explicit loop or broadcast into a pre-allocated buffer to avoid creating a new matrix.
195 |
196 | ### 5. Array Views
197 | Slicing arrays (`A[1:5, :]`) creates a copy.
198 | - Use macros: `@views A[1:5, :]` creates a `SubArray` view automatically.
199 | - Use function calls: `view(A, :, 1)` for specific programmatic control.
200 | - **Caveat:** Be careful with views in dense linear algebra (BLAS); if the memory stride is non-unit, performance may degrade. However, strictly for avoiding allocation, views are required.
201 | - Organize algorithms around column vs. row access patterns to maximize contiguous memory access when using views.
202 |
203 | ### 6. Transposition
204 | Avoid `B = A'` unless it is a wrapper type without materialization.
205 | - Use `transpose!(B, A)` or `adjoint!(B, A)` to move data into a pre-allocated buffer `B`.
206 |
207 | ### 7. Broadcasting and `map!`
208 | - Use `@.` when possible for clarity
209 | - Use `broadcast!(f, dest, args...)` or the syntactic sugar `dest .= f.(args...)` to fuse operations and write directly to `dest`.
210 | - Use `map!(f, dest, src)` for element-wise mapping.
211 |
212 | ### 8. General "Buffer" Management
213 | - When using Enzyme, use in-place variant `f!(out, x)` if there is a vector to be returned. Put the last argument as mutable buffers where required.
214 | - Pass pre-allocated "workspace" vectors/matrices into functions as arguments rather than creating them inside the function body.
215 |
--------------------------------------------------------------------------------
/lectures/about_lectures.md:
--------------------------------------------------------------------------------
1 | ---
2 | jupytext:
3 | text_representation:
4 | extension: .md
5 | format_name: myst
6 | kernelspec:
7 | display_name: Julia
8 | language: julia
9 | name: julia-1.12
10 | ---
11 |
12 | (about)=
13 | # About these Lectures
14 |
15 | ## Overview
16 |
17 | Programming, mathematics and statistics are powerful tools for analyzing the functioning of economies.
18 |
19 | This lecture series provides a hands-on instruction manual.
20 |
21 | Topics include
22 |
23 | - algorithms and numerical methods for studying economic problems,
24 | - related mathematical and statistical concepts, and
25 | - basics of coding skills and software engineering.
26 |
27 | The intended audience is undergraduate students, graduate students and
28 | researchers in economics, finance and related fields.
29 |
30 | ## Julia
31 |
32 | The coding language for this lecture series is Julia.
33 |
34 | Note that there's also a related set of [Python lectures](https://python.quantecon.org).
35 |
36 | In terms of the differences,
37 |
38 | * Python is a general purpose language featuring a huge user community in the sciences and an outstanding scientific and general ecosystem.
39 | * Julia is a more focused language primarily used in technical and scientific computing, with an outstanding ecosystem for cutting-edge methods and algorithms.
40 |
41 | Both are modern, open source, high productivity languages with all the key features needed for
42 | high performance computing.
43 |
44 | While Julia has many features of a general purpose language, its specialization makes it much closer to
45 | using Matlab or Fortran than using a general purpose language - giving it an advantage in being closer
46 | to both mathematical notation and direct implementation of mathematical abstractions.
47 |
48 | Julia has both a large number of useful, well written libraries and many incomplete poorly maintained proofs of concept.
49 |
50 | A major advantage of Julia libraries is that, because Julia itself is sufficiently fast, there is less need to mix in low level languages like C and Fortran.
51 |
52 | As a result, most Julia libraries are written exclusively in Julia.
53 |
54 | Not only does this make the libraries more portable, it makes them much easier to dive into, read, learn from and modify.
55 |
56 | ### A Word of Caution
57 |
58 | The disadvantage of specialization is that Julia tends to be used by domain experts, and consequently
59 | the ecosystem and language for non-mathematical/non-scientific computing tasks is inferior to Python.
60 |
61 | Another disadvantage is that, since it tends to be used by experts and is on the cutting edge, the tooling is
62 | much more fragile and rudimentary than Matlab.
63 |
64 | Thankfully, with the v1.x release of Julia the fragility no longer applies to the language itself - now stable and
65 | carefully managed for [version compatibility](https://semver.org/). However, casual users should
66 | not expect the development tools to quite as stable, or to be comparable to Matlab.
67 |
68 | Nevertheless, the end-result will always be elegant and grounded in mathematical notation and abstractions.
69 |
70 | ## Advantages of Julia
71 |
72 | Despite the short-term cautions, Julia has both immediate and long-run advantages.
73 |
74 | The advantages of the language itself show clearly in the high quality packages, such as
75 |
76 | - Differential Equations: [DifferentialEquations.jl](http://docs.juliadiffeq.org/latest/)
77 | - Function approximation and manipulation: [ApproxFun.jl](https://github.com/JuliaApproximation/ApproxFun.jl)
78 | - Interval Constraint Programming and rigorous root finding: [IntervalRootFinding.jl](https://github.com/JuliaIntervals/IntervalRootFinding.jl)
79 | - GPUs: [CuArrays.jl](https://github.com/JuliaGPU/CuArrays.jl)
80 | - Linear algebra for large-systems (e.g. structured matrices, matrix-free methods, etc.): [IterativeSolvers.jl](https://juliamath.github.io/IterativeSolvers.jl/dev/), [BlockBandedMatrices.jl](https://github.com/JuliaMatrices/BlockBandedMatrices.jl), [InfiniteLinearAlgebra.jl](https://github.com/JuliaMatrices/InfiniteLinearAlgebra.jl), and many others
81 | - Automatic differentiation: [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl) and [Enzyme.jl](https://github.com/EnzymeAD/Enzyme.jl)
82 |
83 | These are in addition to the many mundane but essential packages available. While there are examples of these packages in other languages, no
84 | other language can achieve the combination of performance, mathematical notation, and composition that Julia provides.
85 |
86 | The composition of packages is especially important, and is made possible through Julia's use of something called [multiple-dispatch](https://en.wikipedia.org/wiki/Multiple_dispatch).
87 |
88 | ## Open Source
89 |
90 | All the computing environments we work with are free and open source.
91 |
92 | This means that you, your coauthors and your students can install them and their libraries on all of your computers without cost or concern about licenses.
93 |
94 | Another advantage of open source libraries is that you can read them and learn
95 | how they work.
96 |
97 | For example, let’s say you want to know exactly how [Distributions.jl](https://github.com/JuliaStats/Distributions.jl) implements mean of the exponential function
98 |
99 | No problem: You can go ahead and [read the code](https://github.com/JuliaStats/Distributions.jl/blob/master/src/univariate/continuous/exponential.jl#L56).
100 |
101 | This goes even further since most of Julia is written in Julia. For example, you could see the code for how the standard library calculates the [eigenvalues of a triangular matrix](https://github.com/JuliaLang/julia/blob/master/stdlib/LinearAlgebra/src/triangular.jl#L2594) or calculates the [mean of a range](https://github.com/JuliaLang/julia/blob/master/stdlib/Statistics/src/Statistics.jl#L162)
102 |
103 | Those two examples also provide examples where the "multiple dispatch" allows exploitation of the structure of a problem, leading to specialized algorithms (e.g. if the user calls `eigvals` on a matrix that happens to be triangular, it just needs to return the diagonal).
104 |
105 | While dipping into external code libraries takes a bit of coding maturity, it’s very useful for
106 |
107 | 1. helping you understand the details of a particular implementation, and
108 | 1. building your programming skills by showing you code written by first rate programmers.
109 |
110 | Also, you can modify the library to suit your needs: if the functionality provided is not exactly what you want, you are free to change it.
111 |
112 | Another, more philosophical advantage of open source software is that it conforms to the [scientific ideal of reproducibility](https://en.wikipedia.org/wiki/Scientific_method).
113 |
114 | ## How about Other Languages?
115 |
116 | But why don't you use language XYZ?
117 |
118 | ### MATLAB
119 |
120 | While MATLAB has many nice features, it's starting to show its age.
121 |
122 | It can no longer match Python or Julia in terms of performance and design.
123 |
124 | MATLAB is also proprietary, which comes with its own set of disadvantages.
125 |
126 | In particular, the Achilles Heel of Matlab is its lack of a package management
127 | system, which means that either you need to (1) rely on Matlab's own packages, which
128 | are mostly written for engineers and not economists; (2) write the code
129 | yourself; or (3) use unreliable and manual ways to share code (e.g. email or downloading a zip).
130 |
131 | If you are a structural engineer or designing a microcontroller, then Matlab provides a coherent set of packages that takes care of all of your needs.
132 |
133 | For economists, on the other hand, the expansion in complexity of numerical methods, the need for researchers to
134 | collaborate on code, fix bugs, deploy improvements, and have dependencies (i.e. packages relying on other packges) has increased past what Matlab can handle.
135 |
136 | Given what’s available now, it’s hard to find any good reasons to invest in MATLAB.
137 |
138 | Incidentally, if you decide to jump from MATLAB to Julia, [this cheat-sheet](http://cheatsheets.quantecon.org/) will be useful.
139 |
140 | ### R
141 |
142 | [R](https://cran.r-project.org/) is a very useful open source statistical environment and programming language
143 |
144 | Its primary strength is its [vast collection](https://cran.r-project.org/web/packages) of extension packages
145 |
146 | Julia is more general purpose than R and hence a better fit for this course
147 |
148 | ### C / C++ / Fortran?
149 |
150 | Isn’t Fortran / C / C++ faster than Julia? In which case it must be better, right?
151 |
152 | For the same algorithms, as a compiled language Julia can often achieve a similar level of performance to those languages.
153 |
154 | But even when it doesn't, keep in mind that the correct objective function to minimize: total time = development time + execution time
155 |
156 | In assessing this trade off, it’s necessary to bear in mind that
157 |
158 | - Your time is a far more valuable resource than the computer’s time.
159 | - Languages like Julia are much faster to write and debug in.
160 | - In any one program, the vast majority of CPU time will be spent iterating over just a few lines of your code.
161 |
162 | The other issue with all three languages, as with Matlab, is the lack of a package management system. Collaborating on C++ or Fortran packages and distributing code between researchers is difficult, and many
163 | of the criticisms of matlab equally apply.
164 |
165 | Finally, the first-order question of performance is which algorithm you are using, and whether it exploits the structure of the problem. The right algorithm in Matlab or Python is typically faster than the wrong
166 | algorithm in Fortran - and the right algorithm in Fortran and Julia can be made roughly comparable.
167 |
168 | When considering the performance advantages, remember that the design and package system of Julia make it easy to try out algorithms that exploit structure of the problem. We will investigate this more in {ref}`Introductory Examples `
169 |
170 | #### Last Word
171 |
172 | Writing your entire program in Fortran / C / C++ is best thought of as “premature optimization”
173 |
174 | On this topic we quote the godfather:
175 |
176 | [](https://en.wikipedia.org/wiki/Donald_Knuth)> We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. – Donald Knuth
177 |
178 | But, to put the final part of the quote
179 |
180 | [](https://en.wikipedia.org/wiki/Donald_Knuth)> ... Yet we should not pass up our opportunities in that critical 3%. – Donald Knuth
181 |
182 | Julia is an excellent language to attain those last few percent, without having to resort to C or Fortran code and mix languages in your project
183 |
184 | ## Credits
185 |
186 | These lectures have benefited greatly from comments and suggestions from our
187 | colleagues, students and friends. Special thanks are due to our sponsoring
188 | organization the Alfred P. Sloan Foundation and our research assistants Chase
189 | Coleman, Spencer Lyon and Matthew McKay for innumerable contributions to the
190 | code library and functioning of the website.
191 |
192 | We also thank [Andrij Stachurski](http://drdrij.com/) for his great web
193 | skills, and the many others who have contributed suggestions, bug fixes or
194 | improvements. They include but are not limited to Anmol Bhandari, Long Bui,
195 | Jeong-Hun Choi, David Evans, Xiaojun Guan, Shunsuke Hori, Chenghan Hou, Doc-Jin Jang, Adam Jozefiak,
196 | Qingyin Ma, Akira Matsushita, Tomohito Okabe, Daisuke Oyama, David Pugh, Alex
197 | Olssen, Nathan Palmer, Pooya Rashidi Ravari, Arnav Sood, Bill Tubbs, Dawie van Lill, Natasha Watkins, Pablo Winant, Kaan Yolsever, James Yu, and Yixiao
198 | Zhou.
199 |
200 |
--------------------------------------------------------------------------------
/lectures/multi_agent_models/aiyagari.md:
--------------------------------------------------------------------------------
1 | ---
2 | jupytext:
3 | text_representation:
4 | extension: .md
5 | format_name: myst
6 | kernelspec:
7 | display_name: Julia
8 | language: julia
9 | name: julia-1.12
10 | ---
11 |
12 | (aiyagari)=
13 | ```{raw} html
14 |
19 | ```
20 |
21 | # The Aiyagari Model
22 |
23 | ```{contents} Contents
24 | :depth: 2
25 | ```
26 |
27 | ## Overview
28 |
29 | In this lecture we describe the structure of a class of models that build on work by Truman Bewley {cite}`Bewley1977`.
30 |
31 | ```{only} html
32 | We begin by discussing an example of a Bewley model due to Rao Aiyagari.
33 | ```
34 |
35 | ```{only} latex
36 | We begin by discussing an example of a Bewley model due to [Rao Aiyagari](https://lectures.quantecon.org/_downloads/aiyagari_obit.pdf).
37 | ```
38 |
39 | The model features
40 |
41 | * Heterogeneous agents.
42 | * A single exogenous vehicle for borrowing and lending.
43 | * Limits on amounts individual agents may borrow.
44 |
45 | The Aiyagari model has been used to investigate many topics, including
46 |
47 | * precautionary savings and the effect of liquidity constraints {cite}`Aiyagari1994`
48 | * risk sharing and asset pricing {cite}`Heaton1996`
49 | * the shape of the wealth distribution {cite}`benhabib2015`
50 | * etc., etc., etc.
51 |
52 | ### References
53 |
54 | The primary reference for this lecture is {cite}`Aiyagari1994`.
55 |
56 | A textbook treatment is available in chapter 18 of {cite}`Ljungqvist2012`.
57 |
58 | A continuous time version of the model by SeHyoun Ahn and Benjamin Moll can be found [here](http://nbviewer.jupyter.org/github/QuantEcon/QuantEcon.notebooks/blob/master/aiyagari_continuous_time.ipynb).
59 |
60 | ## The Economy
61 |
62 | ### Households
63 |
64 | Infinitely lived households / consumers face idiosyncratic income shocks.
65 |
66 | A unit interval of *ex ante* identical households face a common borrowing constraint.
67 |
68 | The savings problem faced by a typical household is
69 |
70 | $$
71 | \max \mathbb E \sum_{t=0}^{\infty} \beta^t u(c_t)
72 | $$
73 |
74 | subject to
75 |
76 | $$
77 | a_{t+1} + c_t \leq w z_t + (1 + r) a_t
78 | \quad
79 | c_t \geq 0,
80 | \quad \text{and} \quad
81 | a_t \geq -B
82 | $$
83 |
84 | where
85 |
86 | * $c_t$ is current consumption
87 | * $a_t$ is assets
88 | * $z_t$ is an exogenous component of labor income capturing stochastic unemployment risk, etc.
89 | * $w$ is a wage rate
90 | * $r$ is a net interest rate
91 | * $B$ is the maximum amount that the agent is allowed to borrow
92 |
93 | The exogenous process $\{z_t\}$ follows a finite state Markov chain with given stochastic matrix $P$.
94 |
95 | The wage and interest rate are fixed over time.
96 |
97 | In this simple version of the model, households supply labor inelastically because they do not value leisure.
98 |
99 | ## Firms
100 |
101 | Firms produce output by hiring capital and labor.
102 |
103 | Firms act competitively and face constant returns to scale.
104 |
105 | Since returns to scale are constant the number of firms does not matter.
106 |
107 | Hence we can consider a single (but nonetheless competitive) representative firm.
108 |
109 | The firm's output is
110 |
111 | $$
112 | Y_t = A K_t^{\alpha} N^{1 - \alpha}
113 | $$
114 |
115 | where
116 |
117 | * $A$ and $\alpha$ are parameters with $A > 0$ and $\alpha \in (0, 1)$
118 | * $K_t$ is aggregate capital
119 | * $N$ is total labor supply (which is constant in this simple version of the model)
120 |
121 | The firm's problem is
122 |
123 | $$
124 | max_{K, N} \left\{ A K_t^{\alpha} N^{1 - \alpha} - (r + \delta) K - w N \right\}
125 | $$
126 |
127 | The parameter $\delta$ is the depreciation rate.
128 |
129 | From the first-order condition with respect to capital, the firm's inverse demand for capital is
130 |
131 | ```{math}
132 | :label: aiy_rgk
133 |
134 | r = A \alpha \left( \frac{N}{K} \right)^{1 - \alpha} - \delta
135 | ```
136 |
137 | Using this expression and the firm's first-order condition for labor, we can pin down
138 | the equilibrium wage rate as a function of $r$ as
139 |
140 | ```{math}
141 | :label: aiy_wgr
142 |
143 | w(r) = A (1 - \alpha) (A \alpha / (r + \delta))^{\alpha / (1 - \alpha)}
144 | ```
145 |
146 | ### Equilibrium
147 |
148 | We construct a *stationary rational expectations equilibrium* (SREE).
149 |
150 | In such an equilibrium
151 |
152 | * prices induce behavior that generates aggregate quantities consistent with the prices
153 | * aggregate quantities and prices are constant over time
154 |
155 | In more detail, an SREE lists a set of prices, savings and production policies such that
156 |
157 | * households want to choose the specified savings policies taking the prices as given
158 | * firms maximize profits taking the same prices as given
159 | * the resulting aggregate quantities are consistent with the prices; in particular, the demand for capital equals the supply
160 | * aggregate quantities (defined as cross-sectional averages) are constant
161 |
162 | In practice, once parameter values are set, we can check for an SREE by the following steps
163 |
164 | 1. pick a proposed quantity $K$ for aggregate capital
165 | 1. determine corresponding prices, with interest rate $r$ determined by {eq}`aiy_rgk` and a wage rate $w(r)$ as given in {eq}`aiy_wgr`
166 | 1. determine the common optimal savings policy of the households given these prices
167 | 1. compute aggregate capital as the mean of steady state capital given this savings policy
168 |
169 | If this final quantity agrees with $K$ then we have a SREE.
170 |
171 | ## Code
172 |
173 | Let's look at how we might compute such an equilibrium in practice.
174 |
175 | To solve the household's dynamic programming problem we'll use the [DiscreteDP](https://github.com/QuantEcon/QuantEcon.jl/blob/master/src/markov/ddp.jl) type from [QuantEcon.jl](http://quantecon.org/quantecon-jl).
176 |
177 | Our first task is the least exciting one: write code that maps parameters for a household problem into the `R` and `Q` matrices needed to generate an instance of `DiscreteDP`.
178 |
179 | Below is a piece of boilerplate code that does just this.
180 |
181 | In reading the code, the following information will be helpful
182 |
183 | * `R` needs to be a matrix where `R[s, a]` is the reward at state `s` under action `a`.
184 | * `Q` needs to be a three dimensional array where `Q[s, a, s']` is the probability of transitioning to state `s'` when the current state is `s` and the current action is `a`.
185 |
186 | (For a detailed discussion of `DiscreteDP` see {doc}`this lecture <../dynamic_programming/discrete_dp>`)
187 |
188 | Here we take the state to be $s_t := (a_t, z_t)$, where $a_t$ is assets and $z_t$ is the shock.
189 |
190 | The action is the choice of next period asset level $a_{t+1}$.
191 |
192 | The object also includes a default set of parameters that we'll adopt unless otherwise specified.
193 |
194 |
195 |
196 | ```{code-cell} julia
197 | using LinearAlgebra, Statistics
198 | using LaTeXStrings, Plots, QuantEcon
199 | ```
200 |
201 | ```{code-cell} julia
202 | ---
203 | tags: [remove-cell]
204 | ---
205 | using Test, Random
206 | ```
207 |
208 | ```{code-cell} julia
209 | function Household(; r = 0.01,
210 | w = 1.0,
211 | sigma = 1.0,
212 | beta = 0.96,
213 | z_chain = MarkovChain([0.9 0.1; 0.1 0.9], [0.1; 1.0]),
214 | a_min = 1e-10,
215 | a_max = 18.0,
216 | a_size = 200,
217 | a_vals = range(a_min, a_max, length = a_size),
218 | # -Inf is the utility of dying (0 consumption)
219 | u = sigma == 1 ? x -> log(x) :
220 | x -> (x^(1 - sigma) - 1) / (1 - sigma))
221 |
222 | # Create grids
223 | z_size = length(z_chain.state_values)
224 | n = a_size * z_size
225 | s_vals = gridmake(a_vals, z_chain.state_values)
226 | s_i_vals = gridmake(1:a_size, 1:z_size)
227 |
228 | # Fill in the Q and R
229 | Q = zeros(n, a_size, n)
230 | for next_s_i in 1:size(Q, 3)
231 | for a_i in 1:size(Q, 2)
232 | for s_i in 1:size(Q, 1)
233 | z_i = s_i_vals[s_i, 2]
234 | next_z_i = s_i_vals[next_s_i, 2]
235 | next_a_i = s_i_vals[next_s_i, 1]
236 | if next_a_i == a_i
237 | Q[s_i, a_i, next_s_i] = z_chain.p[z_i, next_z_i]
238 | end
239 | end
240 | end
241 | end
242 |
243 | R = fill(-Inf, n, a_size)
244 | for new_a_i in 1:size(R, 2)
245 | a_new = a_vals[new_a_i]
246 | for s_i in 1:size(R, 1)
247 | a = s_vals[s_i, 1]
248 | z = s_vals[s_i, 2]
249 | c = w * z + (1 + r) * a - a_new
250 | if c > 0
251 | R[s_i, new_a_i] = u(c)
252 | end
253 | end
254 | end
255 | return (; r, w, sigma, beta, z_chain, a_min, a_max, a_size, a_vals, z_size,
256 | n, s_vals, s_i_vals, u, R, Q)
257 | end
258 | ```
259 |
260 | As a first example of what we can do, let's compute and plot an optimal accumulation policy at fixed prices
261 |
262 | ```{code-cell} julia
263 | ---
264 | tags: [remove-cell]
265 | ---
266 | Random.seed!(42);
267 | ```
268 |
269 | ```{code-cell} julia
270 | # Create an instance of Household
271 | am = Household(; a_max = 20.0, r = 0.03, w = 0.956)
272 |
273 | # Use the instance to build a discrete dynamic program
274 | am_ddp = DiscreteDP(am.R, am.Q, am.beta)
275 |
276 | # Solve using policy function iteration
277 | results = solve(am_ddp, PFI)
278 |
279 | # Simplify names
280 | (; z_size, a_size, n, a_vals) = am
281 | z_vals = am.z_chain.state_values
282 |
283 | # Get all optimal actions across the set of
284 | # a indices with z fixed in each column
285 | a_star = reshape([a_vals[results.sigma[s_i]] for s_i in 1:n], a_size, z_size)
286 |
287 | labels = [L"z = %$(z_vals[1])" L"z = %$(z_vals[2])"]
288 | plot(a_vals, a_star, label = labels, lw = 2, alpha = 0.6)
289 | plot!(a_vals, a_vals, label = "", color = :black, linestyle = :dash)
290 | plot!(xlabel = "current assets", ylabel = "next period assets", grid = false)
291 | ```
292 |
293 | ```{code-cell} julia
294 | ---
295 | tags: [remove-cell]
296 | ---
297 | @testset begin
298 | @test a_vals[4] ≈ 0.3015075377869347
299 | @test a_star[4] ≈ 0.2010050252246231
300 | @test results.v[4] ≈ -27.48291672016239
301 | @test z_vals ≈ [0.1, 1.0]
302 | end
303 | ```
304 |
305 | The plot shows asset accumulation policies at different values of the exogenous state.
306 |
307 | Now we want to calculate the equilibrium.
308 |
309 | Let's do this visually as a first pass.
310 |
311 | The following code draws aggregate supply and demand curves.
312 |
313 | The intersection gives equilibrium interest rates and capital
314 |
315 | ```{code-cell} julia
316 | ---
317 | tags: [remove-cell]
318 | ---
319 | Random.seed!(42);
320 | ```
321 |
322 | ```{code-cell} julia
323 |
324 | # Calculate supply of capital for a given r
325 | function prices_to_capital_stock(r; beta, A, N, alpha, delta, a_max)
326 | # Create an instance of Household given the parameters
327 |
328 | # Calculate the equilibrium wages
329 | w = A * (1 - alpha) * (A * alpha / (r + delta))^(alpha / (1 - alpha))
330 | am = Household(; beta, a_max, w, r)
331 |
332 | aiyagari_ddp = DiscreteDP(am.R, am.Q, am.beta)
333 |
334 | # Compute the optimal policy
335 | results = solve(aiyagari_ddp, PFI)
336 |
337 | # Compute the stationary distribution
338 | stationary_probs = stationary_distributions(results.mc)[:, 1][1]
339 |
340 | # Return K
341 | K = dot(am.s_vals[:, 1], stationary_probs)
342 |
343 | # Return capital
344 | return K
345 | end
346 |
347 | # Inverse Demand for capital
348 | function r_inverse_demand(K; A, N, alpha, delta)
349 | return A * alpha * (N / K)^(1 - alpha) - delta
350 | end
351 |
352 | # Create a grid of r values at which to compute demand and supply of capital
353 | r_vals = range(0.005, 0.04, length = 20)
354 |
355 | # Firms' parameters
356 | A = 1
357 | N = 1
358 | alpha = 0.33
359 | beta = 0.96
360 | delta = 0.05
361 | a_max = 20.0
362 |
363 | prices_to_capital_stock(r_vals[1]; A, N, alpha, beta, delta, a_max)
364 |
365 | # Compute supply of capital
366 | k_vals = prices_to_capital_stock.(r_vals; A, N, alpha, beta, delta, a_max)
367 |
368 | r_inverse_demand_vals = r_inverse_demand.(k_vals; A, N, alpha, delta)
369 |
370 | # Plot against demand for capital by firms
371 | labels = ["demand for capital" "supply of capital"]
372 | plot(k_vals, [r_inverse_demand_vals r_vals], label = labels, lw = 2,
373 | alpha = 0.6)
374 | plot!(xlabel = "capital", ylabel = "interest rate", xlim = (2, 14),
375 | ylim = (0.0, 0.1))
376 | ```
--------------------------------------------------------------------------------
/lectures/introduction_dynamics/scalar_dynam.md:
--------------------------------------------------------------------------------
1 | ---
2 | jupytext:
3 | text_representation:
4 | extension: .md
5 | format_name: myst
6 | kernelspec:
7 | display_name: Julia
8 | language: julia
9 | name: julia-1.12
10 | ---
11 |
12 | (scalar_dynam)=
13 | ```{raw} html
14 |
19 | ```
20 |
21 | # {index}`Dynamics in One Dimension `
22 |
23 | ```{contents} Contents
24 | :depth: 2
25 | ```
26 |
27 | ## Overview
28 |
29 | In this lecture we give a quick introduction to discrete time dynamics in one
30 | dimension.
31 |
32 | In one-dimensional models, the state of the system is described by a single variable.
33 |
34 | Although most interesting dynamic models have two or more state variables, the
35 | one-dimensional setting is a good place to learn the foundations of dynamics and build
36 | intuition.
37 |
38 | We'll use the following packages:
39 |
40 | ```{code-cell} julia
41 | using LaTeXStrings, LinearAlgebra, Plots
42 | ```
43 |
44 | ## Some Definitions
45 |
46 | This section sets out the objects of interest and the kinds of properties we study.
47 |
48 | ### Difference Equations
49 |
50 | A **time homogeneous first order difference equation** is an equation of the
51 | form
52 |
53 | ```{math}
54 | :label: sdsod
55 |
56 | x_{t+1} = g(x_t)
57 | ```
58 |
59 | where $g$ is a function from some subset $S$ of $\mathbb R$ to itself.
60 |
61 | Here $S$ is called the **state space** and $x$ is called the **state variable**.
62 |
63 | In the definition,
64 |
65 | * time homogeneity means that $g$ is the same at each time $t$
66 | * first order means dependence on only one lag (i.e., earlier states such as $x_{t-1}$ do not enter into {eq}`sdsod`).
67 |
68 | If $x_0 \in S$ is given, then {eq}`sdsod` recursively defines the sequence
69 |
70 | ```{math}
71 | :label: sdstraj
72 |
73 | x_0, \quad
74 | x_1 = g(x_0), \quad
75 | x_2 = g(x_1) = g(g(x_0)), \quad \text{etc.}
76 | ```
77 |
78 | This sequence is called the **trajectory** of $x_0$ under $g$.
79 |
80 | If we define $g^n$ to be $n$ compositions of $g$ with itself, then we can write the trajectory more simply as $x_t = g^t(x_0)$ for $t \geq 0$.
81 |
82 | ### Example: A Linear Model
83 |
84 | One simple example is the **linear difference equation**
85 |
86 | $$
87 | x_{t+1} = a x_t + b, \qquad S = \mathbb R
88 | $$
89 |
90 | where $a, b$ are fixed constants.
91 |
92 | In this case, given $x_0$, the trajectory {eq}`sdstraj` is
93 |
94 | ```{math}
95 | :label: sdslinmodpath
96 |
97 | x_0, \quad
98 | a x_0 + b, \quad
99 | a^2 x_0 + a b + b, \quad \text{etc.}
100 | ```
101 |
102 | Continuing in this way, and using our knowledge of {doc}`geometric series <../tools_and_techniques/geom_series>`, we find that, for any $t \geq 0$,
103 |
104 | ```{math}
105 | :label: sdslinmod
106 |
107 | x_t = a^t x_0 + b \frac{1 - a^t}{1 - a}
108 | ```
109 |
110 | This is about all we need to know about the linear model.
111 |
112 | We have an exact expression for $x_t$ for all $t$ and hence a full
113 | understanding of the dynamics.
114 |
115 | Notice in particular that $|a| < 1$, then, by {eq}`sdslinmod`, we have
116 |
117 | ```{math}
118 | :label: sdslinmodc
119 |
120 | x_t \to \frac{b}{1 - a} \text{ as } t \to \infty
121 | ```
122 |
123 | regardless of $x_0$
124 |
125 | This is an example of what is called global stability, a topic we return to
126 | below.
127 |
128 | ### Example: A Nonlinear Model
129 |
130 | In the linear example above, we obtained an exact analytical expression for $x_t$
131 | in terms of arbitrary $t$ and $x_0$.
132 |
133 | This made analysis of dynamics very easy.
134 |
135 | When models are nonlinear, however, the situation can be quite different.
136 |
137 | For example, consider the law of motion for the Solow growth model, a simplified version of which is
138 |
139 | ```{math}
140 | :label: solow_lom2
141 |
142 | k_{t+1} = s z k_t^{\alpha} + (1 - \delta) k_t
143 | ```
144 |
145 | Here $k$ is capital stock and $s, z, \alpha, \delta$ are positive
146 | parameters with $0 < \alpha, \delta < 1$.
147 |
148 | If you try to iterate like we did in {eq}`sdslinmodpath`, you will find that
149 | the algebra gets messy quickly.
150 |
151 | Analyzing the dynamics of this model requires a different method (see below).
152 |
153 | ### Stability
154 |
155 | A **steady state** of the difference equation $x_{t+1} = g(x_t)$ is a
156 | point $x^*$ in $S$ such that $x^* = g(x^*)$.
157 |
158 | In other words, $x^*$ is a **fixed point** of the function $g$ in
159 | $S$.
160 |
161 | For example, for the linear model $x_{t+1} = a x_t + b$, you can use the
162 | definition to check that
163 |
164 | * $x^* := b/(1-a)$ is a steady state whenever $a \not= 1$.
165 | * if $a = 1$ and $b=0$, then every $x \in \mathbb R$ is a
166 | steady state.
167 | * if $a = 1$ and $b \not= 0$, then the linear model has no steady
168 | state in $\mathbb R$.
169 |
170 | A steady state $x^*$ of $x_{t+1} = g(x_t)$ is called
171 | **globally stable** if, for all $x_0 \in S$,
172 |
173 | $$
174 | x_t = g^t(x_0) \to x^* \text{ as } t \to \infty
175 | $$
176 |
177 | For example, in the linear model $x_{t+1} = a x_t + b$ with $a
178 | \not= 1$, the steady state $x^*$
179 |
180 | * is globally stable if $|a| < 1$ and
181 | * fails to be globally stable otherwise.
182 |
183 | This follows directly from {eq}`sdslinmod`.
184 |
185 | A steady state $x^*$ of $x_{t+1} = g(x_t)$ is called
186 | **locally stable** if there exists an $\epsilon > 0$ such that
187 |
188 | $$
189 | | x_0 - x^* | < \epsilon
190 | \; \implies \;
191 | x_t = g^t(x_0) \to x^* \text{ as } t \to \infty
192 | $$
193 |
194 | Obviously every globally stable steady state is also locally stable.
195 |
196 | We will see examples below where the converse is not true.
197 |
198 | ## Graphical Analysis
199 |
200 | As we saw above, analyzing the dynamics for nonlinear models is nontrivial.
201 |
202 | There is no single way to tackle all nonlinear models.
203 |
204 | However, there is one technique for one-dimensional models that provides a
205 | great deal of intuition.
206 |
207 | This is a graphical approach based on **45 degree diagrams**.
208 |
209 | Let's look at an example: the Solow model with dynamics given in {eq}`solow_lom2`.
210 |
211 | We begin with some plotting code that you can ignore at first reading.
212 |
213 | The function of the code is to produce 45 degree diagrams and time series
214 | plots.
215 |
216 | ```{code-cell} julia
217 | # Iterates a function from an initial condition
218 | function iterate_map(f, x0, T)
219 | x = zeros(T + 1)
220 | x[1] = x0
221 | for t in 2:(T + 1)
222 | x[t] = f(x[t - 1])
223 | end
224 | return x
225 | end
226 |
227 | function plot45(f, xmin, xmax, x0, T; num_points = 100, label = L"g(k)",
228 | xlabel = "k")
229 | # Plot the function and the 45 degree line
230 | x_grid = range(xmin, xmax, num_points)
231 | plt = plot(x_grid, f.(x_grid); xlim = (xmin, xmax), ylim = (xmin, xmax),
232 | linecolor = :black, lw = 2, label)
233 | plot!(x_grid, x_grid; linecolor = :blue, lw = 2, label = nothing)
234 |
235 | # Iterate map and add ticks
236 | x = iterate_map(f, x0, T)
237 | xticks!(x, [L"%$(xlabel)_{%$i}" for i in 0:T])
238 | yticks!(x, [L"%$(xlabel)_{%$i}" for i in 0:T])
239 |
240 | # Plot arrows and dashes
241 | for i in 1:T
242 | plot!([x[i], x[i]], [x[i], x[i + 1]], arrow = :closed, linecolor = :black,
243 | alpha = 0.5, label = nothing)
244 | plot!([x[i], x[i + 1]], [x[i + 1], x[i + 1]], arrow = :closed,
245 | linecolor = :black, alpha = 0.5, label = nothing)
246 | plot!([x[i + 1], x[i + 1]], [0, x[i + 1]], linestyle = :dash,
247 | linecolor = :black, alpha = 0.5, label = nothing)
248 | end
249 | plot!([x[1], x[1]], [0, x[1]], linestyle = :dash, linecolor = :black,
250 | alpha = 0.5, label = nothing)
251 | end
252 |
253 | function ts_plot(f, x0, T; xlabel = L"t", label = L"k_t")
254 | x = iterate_map(f, x0, T)
255 | plot(0:T, x; xlabel, label)
256 | plot!(0:T, x; seriestype = :scatter, mc = :blue, alpha = 0.7, label = nothing)
257 | end
258 | ```
259 |
260 | Let's create a 45 degree diagram for the Solow model with a fixed set of
261 | parameters
262 |
263 | ```{code-cell} julia
264 | p = (A = 2, s = 0.3, alpha = 0.3, delta = 0.4, xmin = 0, xmax = 4)
265 | ```
266 |
267 | Here's the update function corresponding to the model.
268 |
269 | ```{code-cell} julia
270 | g(k; p) = p.A * p.s * k^p.alpha + (1 - p.delta) * k
271 | ```
272 |
273 | Here is the 45 degree plot.
274 |
275 | ```{code-cell} julia
276 | plot45(k -> g(k; p), p.xmin, p.xmax, 0, 6)
277 | ```
278 |
279 | The plot shows the function $g$ and the 45 degree line.
280 |
281 | Think of $k_t$ as a value on the horizontal axis.
282 |
283 | To calculate $k_{t+1}$, we can use the graph of $g$ to see its
284 | value on the vertical axis.
285 |
286 | Clearly,
287 |
288 | * If $g$ lies above the 45 degree line at this point, then we have $k_{t+1} > k_t$.
289 | * If $g$ lies below the 45 degree line at this point, then we have $k_{t+1} < k_t$.
290 | * If $g$ hits the 45 degree line at this point, then we have $k_{t+1} = k_t$, so $k_t$ is a steady state.
291 |
292 | For the Solow model, there are two steady states when $S = \mathbb R_+ =
293 | [0, \infty)$.
294 |
295 | * the origin $k=0$
296 | * the unique positive number such that $k = s z k^{\alpha} + (1 - \delta) k$.
297 |
298 | By using some algebra, we can show that in the second case, the steady state is
299 |
300 | $$
301 | k^* = \left( \frac{sz}{\delta} \right)^{1/(1-\alpha)}
302 | $$
303 |
304 | ### Trajectories
305 |
306 | By the preceding discussion, in regions where $g$ lies above the 45 degree line, we know that the trajectory is increasing.
307 |
308 | The next figure traces out a trajectory in such a region so we can see this more clearly.
309 |
310 | The initial condition is $k_0 = 0.25$.
311 |
312 | ```{code-cell} julia
313 | k0 = 0.25
314 | plot45(k -> g(k; p), p.xmin, p.xmax, k0, 5)
315 | ```
316 |
317 | We can plot the time series of capital corresponding to the figure above as
318 | follows:
319 |
320 | ```{code-cell} julia
321 | ts_plot(k -> g(k; p), k0, 5)
322 | ```
323 |
324 | Here's a somewhat longer view:
325 |
326 | ```{code-cell} julia
327 | ts_plot(k -> g(k; p), k0, 20)
328 | ```
329 |
330 | When capital stock is higher than the unique positive steady state, we see that
331 | it declines:
332 |
333 | ```{code-cell} julia
334 | k0 = 2.95
335 | plot45(k -> g(k; p), p.xmin, p.xmax, k0, 5)
336 | ```
337 |
338 | Here is the time series:
339 |
340 | ```{code-cell} julia
341 | ts_plot(k -> g(k; p), k0, 8)
342 | ```
343 |
344 | ### Complex Dynamics
345 |
346 | The Solow model is nonlinear but still generates very regular dynamics.
347 |
348 | One model that generates irregular dynamics is the **quadratic map**
349 |
350 | $$
351 | g(x) = 4 x (1 - x),
352 | \qquad x \in [0, 1]
353 | $$
354 |
355 | Let's have a look at the 45 degree diagram.
356 |
357 | ```{code-cell} julia
358 | xmin, xmax = 0, 1
359 | g(k) = 4 * k * (1 - k)
360 | x0 = 0.3
361 | plot45(g, xmin, xmax, 0.1, 0)
362 | ```
363 |
364 | Now let's look at a typical trajectory.
365 |
366 | ```{code-cell} julia
367 | plot45(g, xmin, xmax, 0.1, 6)
368 | ```
369 |
370 | Notice how irregular it is.
371 |
372 | Here is the corresponding time series plot.
373 |
374 | ```{code-cell} julia
375 | ts_plot(g, x0, 6)
376 | ```
377 |
378 | The irregularity is even clearer over a longer time horizon:
379 |
380 | ```{code-cell} julia
381 | ts_plot(g, x0, 20)
382 | ```
383 |
384 | ## Exercises
385 | ### Exercise 1
386 |
387 | Consider again the linear model $x_{t+1} = a x_t + b$ with $a
388 | \not=1$.
389 |
390 | The unique steady state is $b / (1 - a)$.
391 |
392 | The steady state is globally stable if $|a| < 1$.
393 |
394 | Try to illustrate this graphically by looking at a range of initial conditions.
395 |
396 | What differences do you notice in the cases $a \in (-1, 0)$ and $a
397 | \in (0, 1)$?
398 |
399 | Use $a=0.5$ and then $a=-0.5$ and study the trajectories
400 |
401 | Set $b=1$ throughout.
402 |
403 | ## Solutions
404 |
405 | ### Exercise 1
406 | We will start with the case $a=0.5$.
407 |
408 | Let's set up the model and plotting region:
409 |
410 | ```{code-cell} julia
411 | q = (a = 0.5, b = 1, xmin = -1, xmax = 3)
412 | g(k; q) = q.a * k + q.b
413 | ```
414 |
415 | Now let's plot a trajectory:
416 |
417 | ```{code-cell} julia
418 | x0 = -0.5
419 | plot45(k -> g(k; q), q.xmin, q.xmax, x0, 5)
420 | ```
421 |
422 | Here is the corresponding time series, which converges towards the steady
423 | state.
424 |
425 | ```{code-cell} julia
426 | ts_plot(k -> g(k; q), x0, 10)
427 | ```
428 |
429 | Now let's try $a=-0.5$ and see what differences we observe.
430 |
431 | Let's set up the model and plotting region:
432 |
433 | ```{code-cell} julia
434 | r = (a = -0.5, b = 1, xmin = -1, xmax = 3)
435 | g(k; r) = r.a * k + r.b
436 | ```
437 |
438 | Now let's plot a trajectory:
439 |
440 | ```{code-cell} julia
441 | x0 = -0.5
442 | plot45(k -> g(k; r), r.xmin, r.xmax, x0, 5)
443 | ```
444 |
445 | Here is the corresponding time series, which converges towards the steady
446 | state.
447 |
448 | ```{code-cell} julia
449 | ts_plot(k -> g(k; r), x0, 10)
450 | ```
451 |
452 | Once again, we have convergence to the steady state but the nature of
453 | convergence differs.
454 |
455 | In particular, the time series jumps from above the steady state to below it
456 | and back again.
457 |
458 | In the current context, the series is said to exhibit **damped oscillations**.
459 |
--------------------------------------------------------------------------------
/lectures/introduction_dynamics/short_path.md:
--------------------------------------------------------------------------------
1 | ---
2 | jupytext:
3 | text_representation:
4 | extension: .md
5 | format_name: myst
6 | kernelspec:
7 | display_name: Julia
8 | language: julia
9 | name: julia-1.12
10 | ---
11 |
12 | (short_path)=
13 | ```{raw} html
14 |
19 | ```
20 |
21 | # Shortest Paths
22 |
23 | ```{index} single: Dynamic Programming; Shortest Paths
24 | ```
25 |
26 | ```{contents} Contents
27 | :depth: 2
28 | ```
29 |
30 | ## Overview
31 |
32 | The shortest path problem is a [classic problem](https://en.wikipedia.org/wiki/Shortest_path) in mathematics and computer science with applications in
33 |
34 | * Economics (sequential decision making, analysis of social networks, etc.)
35 | * Operations research and transportation
36 | * Robotics and artificial intelligence
37 | * Telecommunication network design and routing
38 | * etc., etc.
39 |
40 | Variations of the methods we discuss in this lecture are used millions of times every day, in applications such as
41 |
42 | * Google Maps
43 | * routing packets on the internet
44 |
45 | For us, the shortest path problem also provides a nice introduction to the logic of **dynamic programming**.
46 |
47 | Dynamic programming is an extremely powerful optimization technique that we apply in many lectures on this site.
48 |
49 | ## Outline of the Problem
50 |
51 | The shortest path problem is one of finding how to traverse a [graph](https://en.wikipedia.org/wiki/Graph_%28mathematics%29) from one specified node to another at minimum cost.
52 |
53 | Consider the following graph
54 |
55 | ```{figure} /_static/figures/graph.png
56 | :width: 100%
57 | ```
58 |
59 | We wish to travel from node (vertex) A to node G at minimum cost.
60 |
61 | * Arrows (edges) indicate the movements we can take.
62 | * Numbers on edges indicate the cost of traveling that edge.
63 |
64 | Possible interpretations of the graph include
65 |
66 | * Minimum cost for supplier to reach a destination.
67 | * Routing of packets on the internet (minimize time).
68 | * Etc., etc.
69 |
70 | For this simple graph, a quick scan of the edges shows that the optimal paths are
71 |
72 | * A, C, F, G at cost 8
73 |
74 | ```{figure} /_static/figures/graph4.png
75 | :width: 100%
76 | ```
77 |
78 | * A, D, F, G at cost 8
79 |
80 | ```{figure} /_static/figures/graph3.png
81 | :width: 100%
82 | ```
83 |
84 | ## Finding Least-Cost Paths
85 |
86 | For large graphs we need a systematic solution.
87 |
88 | Let $J(v)$ denote the minimum cost-to-go from node $v$, understood as the total cost from $v$ if we take the best route.
89 |
90 | Suppose that we know $J(v)$ for each node $v$, as shown below for the graph from the preceding example
91 |
92 | ```{figure} /_static/figures/graph2.png
93 | :width: 100%
94 | ```
95 |
96 | Note that $J(G) = 0$.
97 |
98 | The best path can now be found as follows
99 |
100 | * Start at A.
101 | * From node v, move to any node that solves
102 |
103 | ```{math}
104 | :label: spprebell
105 |
106 | \min_{w \in F_v} \{ c(v, w) + J(w) \}
107 | ```
108 |
109 | where
110 |
111 | * $F_v$ is the set of nodes that can be reached from $v$ in one step
112 | * $c(v, w)$ is the cost of traveling from $v$ to $w$
113 |
114 | Hence, if we know the function $J$, then finding the best path is almost trivial.
115 |
116 | But how to find $J$?
117 |
118 | Some thought will convince you that, for every node $v$,
119 | the function $J$ satisfies
120 |
121 | ```{math}
122 | :label: spbell
123 |
124 | J(v) = \min_{w \in F_v} \{ c(v, w) + J(w) \}
125 | ```
126 |
127 | This is known as the *Bellman equation*, after the mathematician Richard Bellman.
128 |
129 | ## Solving for $J$
130 |
131 | The standard algorithm for finding $J$ is to start with
132 |
133 | ```{math}
134 | :label: spguess
135 |
136 | J_0(v) = M \text{ if } v \not= \text{ destination, else } J_0(v) = 0
137 | ```
138 |
139 | where $M$ is some large number.
140 |
141 | Now we use the following algorithm
142 |
143 | 1. Set $n = 0$.
144 | 1. Set $J_{n+1} (v) = \min_{w \in F_v} \{ c(v, w) + J_n(w) \}$ for all $v$.
145 | 1. If $J_{n+1}$ and $J_n$ are not equal then increment $n$, go to 2.
146 |
147 | In general, this sequence converges to $J$---the proof is omitted.
148 |
149 | ## Exercises
150 |
151 | (short_path_ex1)=
152 | ### Exercise 1
153 |
154 | Use the algorithm given above to find the optimal path (and its cost) for the
155 | following graph.
156 |
157 | The graph is **directed**: from each node you may move only to the destinations
158 | listed in its adjacency list (e.g., you can travel from `0` to `1`, but not from
159 | `1` back to `0` unless that edge is explicitly listed). Treat node `0` as the
160 | start and node `99` as the destination. As an extension, you can symmetrize the
161 | edges to create an undirected version and compare the resulting path and cost.
162 |
163 |
164 | ```{code-cell} julia
165 | using LinearAlgebra, Statistics
166 | ```
167 |
168 | ```{code-cell} julia
169 | ---
170 | tags: [remove-cell]
171 | ---
172 | using Test
173 | ```
174 |
175 | ```{code-cell} julia
176 | graph = Dict(zip(0:99,
177 | [
178 | [(14, 72.21), (8, 11.11), (1, 0.04)],
179 | [(13, 64.94), (6, 20.59), (46, 1247.25)],
180 | [(45, 1561.45), (31, 166.8), (66, 54.18)],
181 | [(11, 42.43), (6, 2.06), (20, 133.65)],
182 | [(7, 1.02), (5, 0.73), (75, 3706.67)],
183 | [(11, 34.54), (7, 3.33), (45, 1382.97)],
184 | [(10, 13.1), (9, 0.72), (31, 63.17)],
185 | [(10, 5.85), (9, 3.15), (50, 478.14)],
186 | [(12, 3.18), (11, 7.45), (69, 577.91)],
187 | [(20, 16.53), (13, 4.42), (70, 2454.28)],
188 | [(16, 25.16), (12, 1.87), (89, 5352.79)],
189 | [(20, 65.08), (18, 37.55), (94, 4961.32)],
190 | [(28, 170.04), (24, 34.32), (84, 3914.62)],
191 | [(40, 475.33), (38, 236.33), (60, 2135.95)],
192 | [(24, 38.65), (16, 2.7), (67, 1878.96)],
193 | [(18, 2.57), (17, 1.01), (91, 3597.11)],
194 | [(38, 278.71), (19, 3.49), (36, 392.92)],
195 | [(23, 26.45), (22, 24.78), (76, 783.29)],
196 | [(28, 55.84), (23, 16.23), (91, 3363.17)],
197 | [(28, 70.54), (20, 0.24), (26, 20.09)],
198 | [(33, 145.8), (24, 9.81), (98, 3523.33)],
199 | [(31, 27.06), (28, 36.65), (56, 626.04)],
200 | [(40, 124.22), (39, 136.32), (72, 1447.22)],
201 | [(33, 22.37), (26, 2.66), (52, 336.73)],
202 | [(28, 14.25), (26, 1.8), (66, 875.19)],
203 | [(35, 45.55), (32, 36.58), (70, 1343.63)],
204 | [(42, 122.0), (27, 0.01), (47, 135.78)],
205 | [(43, 246.24), (35, 48.1), (65, 480.55)],
206 | [(36, 15.52), (34, 21.79), (82, 2538.18)],
207 | [(33, 12.61), (32, 4.22), (64, 635.52)],
208 | [(35, 13.95), (33, 5.61), (98, 2616.03)],
209 | [(44, 125.88), (36, 20.44), (98, 3350.98)],
210 | [(35, 1.46), (34, 3.33), (97, 2613.92)],
211 | [(47, 111.54), (41, 3.23), (81, 1854.73)],
212 | [(48, 129.45), (42, 51.52), (73, 1075.38)],
213 | [(50, 78.81), (41, 2.09), (52, 17.57)],
214 | [(57, 260.46), (54, 101.08), (71, 1171.6)],
215 | [(46, 80.49), (38, 0.36), (75, 269.97)],
216 | [(42, 8.78), (40, 1.79), (93, 2767.85)],
217 | [(41, 1.34), (40, 0.95), (50, 39.88)],
218 | [(54, 53.46), (47, 28.57), (75, 548.68)],
219 | [(54, 162.24), (46, 0.28), (53, 18.23)],
220 | [(72, 437.49), (47, 10.08), (59, 141.86)],
221 | [(60, 116.23), (54, 95.06), (98, 2984.83)],
222 | [(47, 2.14), (46, 1.56), (91, 807.39)],
223 | [(49, 15.51), (47, 3.68), (58, 79.93)],
224 | [(67, 65.48), (57, 27.5), (52, 22.68)],
225 | [(61, 172.64), (56, 49.31), (50, 2.82)],
226 | [(60, 66.44), (59, 34.52), (99, 2564.12)],
227 | [(56, 10.89), (50, 0.51), (78, 53.79)],
228 | [(55, 20.1), (53, 1.38), (85, 251.76)],
229 | [(60, 73.79), (59, 23.67), (98, 2110.67)],
230 | [(66, 123.03), (64, 102.41), (94, 1471.8)],
231 | [(67, 88.35), (56, 4.33), (72, 22.85)],
232 | [(73, 238.61), (59, 24.3), (88, 967.59)],
233 | [(64, 60.8), (57, 2.13), (84, 86.09)],
234 | [(61, 11.06), (57, 0.02), (76, 197.03)],
235 | [(60, 7.01), (58, 0.46), (86, 701.09)],
236 | [(65, 34.32), (64, 29.85), (83, 556.7)],
237 | [(71, 0.67), (60, 0.72), (90, 820.66)],
238 | [(67, 1.63), (65, 4.76), (76, 48.03)],
239 | [(64, 4.88), (63, 0.95), (98, 1057.59)],
240 | [(76, 38.43), (64, 2.94), (91, 132.23)],
241 | [(75, 56.34), (72, 70.08), (66, 4.43)],
242 | [(76, 11.98), (65, 0.3), (80, 47.73)],
243 | [(73, 33.23), (66, 0.64), (94, 594.93)],
244 | [(73, 37.53), (68, 2.66), (98, 395.63)],
245 | [(70, 0.98), (68, 0.09), (82, 153.53)],
246 | [(71, 1.66), (70, 3.35), (94, 232.1)],
247 | [(73, 8.99), (70, 0.06), (99, 247.8)],
248 | [(73, 8.37), (72, 1.5), (76, 27.18)],
249 | [(91, 284.64), (74, 8.86), (89, 104.5)],
250 | [(92, 133.06), (84, 102.77), (76, 15.32)],
251 | [(90, 243.0), (76, 1.4), (83, 52.22)],
252 | [(78, 8.08), (76, 0.52), (81, 1.07)],
253 | [(77, 1.19), (76, 0.81), (92, 68.53)],
254 | [(78, 2.36), (77, 0.45), (85, 13.18)],
255 | [(86, 64.32), (78, 0.98), (80, 8.94)],
256 | [(81, 2.59), (98, 355.9)],
257 | [(91, 22.35), (85, 1.45), (81, 0.09)],
258 | [(98, 264.34), (88, 28.78), (92, 121.87)],
259 | [(92, 99.89), (89, 39.52), (94, 99.78)],
260 | [(93, 11.99), (88, 28.05), (91, 47.44)],
261 | [(88, 5.78), (86, 8.75), (94, 114.95)],
262 | [(98, 121.05), (94, 30.41), (89, 19.14)],
263 | [(89, 4.9), (87, 2.66), (97, 94.51)],
264 | [(97, 85.09)],
265 | [(92, 21.23), (91, 11.14), (88, 0.21)],
266 | [(98, 6.12), (91, 6.83), (93, 1.31)],
267 | [(99, 82.12), (97, 36.97)],
268 | [(99, 50.99), (94, 10.47), (96, 23.53)],
269 | [(97, 22.17)],
270 | [(99, 34.68), (97, 11.24), (96, 10.83)],
271 | [(99, 32.77), (97, 6.71), (94, 0.19)],
272 | [(96, 2.03), (98, 5.91)],
273 | [(99, 0.27), (98, 6.17)],
274 | [(99, 5.87), (97, 0.43), (98, 3.32)],
275 | [(98, 0.3)],
276 | [(99, 0.33)],
277 | [(99, 0.0)],
278 | ]))
279 | ```
280 |
281 | The cost from node 68 to node 71 is 1.66 and so on.
282 |
283 | ## Solutions
284 |
285 | ### Exercise 1
286 |
287 | ```{code-cell} julia
288 | function value_iteration(graph; dest = maximum(keys(graph)))
289 | J = Dict(node => (node == dest ? 0.0 : Inf) for node in keys(graph))
290 | updated = true
291 | while updated
292 | updated = false
293 | for (node, edges) in graph
294 | node == dest && continue
295 | best = minimum(cost + J[child] for (child, cost) in edges)
296 | if best != J[node]
297 | J[node] = best
298 | updated = true
299 | end
300 | end
301 | end
302 | return J
303 | end
304 |
305 | function best_path(J, graph; start = minimum(keys(graph)), dest = maximum(keys(graph)))
306 | path = Int[]
307 | cost = 0.0
308 | current = start
309 | while current != dest
310 | push!(path, current)
311 | edges = graph[current]
312 | next_node, edge_cost = edges[1]
313 | best_total = edge_cost + J[next_node]
314 | for (child, c) in Iterators.drop(edges, 1)
315 | total = c + J[child]
316 | if total < best_total
317 | best_total = total
318 | next_node = child
319 | edge_cost = c
320 | end
321 | end
322 | current = next_node
323 | cost += edge_cost
324 | end
325 | push!(path, dest)
326 | return path, cost
327 | end
328 |
329 | J = value_iteration(graph)
330 | path, total_cost = best_path(J, graph)
331 | total_cost = round(total_cost; digits = 2)
332 |
333 | for node in path
334 | println("node $node")
335 | end
336 | println("Cost: $total_cost")
337 | ```
338 |
339 | ```{code-cell} julia
340 | ---
341 | tags: [remove-cell]
342 | ---
343 | sum_costs = 0.0
344 | current_location, destination = extrema(keys(graph))
345 | while current_location != destination
346 | println("node $current_location")
347 | running_min = 1e10
348 | minimizer_dest = Inf
349 | minimizer_cost = 1e10
350 | for (dest, cost) in graph[current_location]
351 | cost_of_path = cost + J[dest]
352 | if cost_of_path < running_min
353 | running_min = cost_of_path
354 | minimizer_cost = cost
355 | minimizer_dest = dest
356 | end
357 | end
358 |
359 | current_location = minimizer_dest
360 | sum_costs += minimizer_cost
361 | end
362 |
363 | sum_costs = round(sum_costs, digits = 2)
364 |
365 | @test sum_costs ≈ 160.55
366 | ```
367 |
--------------------------------------------------------------------------------