diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..4ea99c2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,395 @@
+Attribution 4.0 International
+
+=======================================================================
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and
+does not provide legal services or legal advice. Distribution of
+Creative Commons public licenses does not create a lawyer-client or
+other relationship. Creative Commons makes its licenses and related
+information available on an "as-is" basis. Creative Commons gives no
+warranties regarding its licenses, any material licensed under their
+terms and conditions, or any related information. Creative Commons
+disclaims all liability for damages resulting from their use to the
+fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and
+conditions that creators and other rights holders may use to share
+original works of authorship and other material subject to copyright
+and certain other rights specified in the public license below. The
+following considerations are for informational purposes only, are not
+exhaustive, and do not form part of our licenses.
+
+ Considerations for licensors: Our public licenses are
+ intended for use by those authorized to give the public
+ permission to use material in ways otherwise restricted by
+ copyright and certain other rights. Our licenses are
+ irrevocable. Licensors should read and understand the terms
+ and conditions of the license they choose before applying it.
+ Licensors should also secure all rights necessary before
+ applying our licenses so that the public can reuse the
+ material as expected. Licensors should clearly mark any
+ material not subject to the license. This includes other CC-
+ licensed material, or material used under an exception or
+ limitation to copyright. More considerations for licensors:
+ wiki.creativecommons.org/Considerations_for_licensors
+
+ Considerations for the public: By using one of our public
+ licenses, a licensor grants the public permission to use the
+ licensed material under specified terms and conditions. If
+ the licensor's permission is not necessary for any reason--for
+ example, because of any applicable exception or limitation to
+ copyright--then that use is not regulated by the license. Our
+ licenses grant only permissions under copyright and certain
+ other rights that a licensor has authority to grant. Use of
+ the licensed material may still be restricted for other
+ reasons, including because others have copyright or other
+ rights in the material. A licensor may make special requests,
+ such as asking that all changes be marked or described.
+ Although not required by our licenses, you are encouraged to
+ respect those requests where reasonable. More considerations
+ for the public:
+ wiki.creativecommons.org/Considerations_for_licensees
+
+=======================================================================
+
+Creative Commons Attribution 4.0 International Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree
+to be bound by the terms and conditions of this Creative Commons
+Attribution 4.0 International Public License ("Public License"). To the
+extent this Public License may be interpreted as a contract, You are
+granted the Licensed Rights in consideration of Your acceptance of
+these terms and conditions, and the Licensor grants You such rights in
+consideration of benefits the Licensor receives from making the
+Licensed Material available under these terms and conditions.
+
+
+Section 1 -- Definitions.
+
+ a. Adapted Material means material subject to Copyright and Similar
+ Rights that is derived from or based upon the Licensed Material
+ and in which the Licensed Material is translated, altered,
+ arranged, transformed, or otherwise modified in a manner requiring
+ permission under the Copyright and Similar Rights held by the
+ Licensor. For purposes of this Public License, where the Licensed
+ Material is a musical work, performance, or sound recording,
+ Adapted Material is always produced where the Licensed Material is
+ synched in timed relation with a moving image.
+
+ b. Adapter's License means the license You apply to Your Copyright
+ and Similar Rights in Your contributions to Adapted Material in
+ accordance with the terms and conditions of this Public License.
+
+ c. Copyright and Similar Rights means copyright and/or similar rights
+ closely related to copyright including, without limitation,
+ performance, broadcast, sound recording, and Sui Generis Database
+ Rights, without regard to how the rights are labeled or
+ categorized. For purposes of this Public License, the rights
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar
+ Rights.
+
+ d. Effective Technological Measures means those measures that, in the
+ absence of proper authority, may not be circumvented under laws
+ fulfilling obligations under Article 11 of the WIPO Copyright
+ Treaty adopted on December 20, 1996, and/or similar international
+ agreements.
+
+ e. Exceptions and Limitations means fair use, fair dealing, and/or
+ any other exception or limitation to Copyright and Similar Rights
+ that applies to Your use of the Licensed Material.
+
+ f. Licensed Material means the artistic or literary work, database,
+ or other material to which the Licensor applied this Public
+ License.
+
+ g. Licensed Rights means the rights granted to You subject to the
+ terms and conditions of this Public License, which are limited to
+ all Copyright and Similar Rights that apply to Your use of the
+ Licensed Material and that the Licensor has authority to license.
+
+ h. Licensor means the individual(s) or entity(ies) granting rights
+ under this Public License.
+
+ i. Share means to provide material to the public by any means or
+ process that requires permission under the Licensed Rights, such
+ as reproduction, public display, public performance, distribution,
+ dissemination, communication, or importation, and to make material
+ available to the public including in ways that members of the
+ public may access the material from a place and at a time
+ individually chosen by them.
+
+ j. Sui Generis Database Rights means rights other than copyright
+ resulting from Directive 96/9/EC of the European Parliament and of
+ the Council of 11 March 1996 on the legal protection of databases,
+ as amended and/or succeeded, as well as other essentially
+ equivalent rights anywhere in the world.
+
+ k. You means the individual or entity exercising the Licensed Rights
+ under this Public License. Your has a corresponding meaning.
+
+
+Section 2 -- Scope.
+
+ a. License grant.
+
+ 1. Subject to the terms and conditions of this Public License,
+ the Licensor hereby grants You a worldwide, royalty-free,
+ non-sublicensable, non-exclusive, irrevocable license to
+ exercise the Licensed Rights in the Licensed Material to:
+
+ a. reproduce and Share the Licensed Material, in whole or
+ in part; and
+
+ b. produce, reproduce, and Share Adapted Material.
+
+ 2. Exceptions and Limitations. For the avoidance of doubt, where
+ Exceptions and Limitations apply to Your use, this Public
+ License does not apply, and You do not need to comply with
+ its terms and conditions.
+
+ 3. Term. The term of this Public License is specified in Section
+ 6(a).
+
+ 4. Media and formats; technical modifications allowed. The
+ Licensor authorizes You to exercise the Licensed Rights in
+ all media and formats whether now known or hereafter created,
+ and to make technical modifications necessary to do so. The
+ Licensor waives and/or agrees not to assert any right or
+ authority to forbid You from making technical modifications
+ necessary to exercise the Licensed Rights, including
+ technical modifications necessary to circumvent Effective
+ Technological Measures. For purposes of this Public License,
+ simply making modifications authorized by this Section 2(a)
+ (4) never produces Adapted Material.
+
+ 5. Downstream recipients.
+
+ a. Offer from the Licensor -- Licensed Material. Every
+ recipient of the Licensed Material automatically
+ receives an offer from the Licensor to exercise the
+ Licensed Rights under the terms and conditions of this
+ Public License.
+
+ b. No downstream restrictions. You may not offer or impose
+ any additional or different terms or conditions on, or
+ apply any Effective Technological Measures to, the
+ Licensed Material if doing so restricts exercise of the
+ Licensed Rights by any recipient of the Licensed
+ Material.
+
+ 6. No endorsement. Nothing in this Public License constitutes or
+ may be construed as permission to assert or imply that You
+ are, or that Your use of the Licensed Material is, connected
+ with, or sponsored, endorsed, or granted official status by,
+ the Licensor or others designated to receive attribution as
+ provided in Section 3(a)(1)(A)(i).
+
+ b. Other rights.
+
+ 1. Moral rights, such as the right of integrity, are not
+ licensed under this Public License, nor are publicity,
+ privacy, and/or other similar personality rights; however, to
+ the extent possible, the Licensor waives and/or agrees not to
+ assert any such rights held by the Licensor to the limited
+ extent necessary to allow You to exercise the Licensed
+ Rights, but not otherwise.
+
+ 2. Patent and trademark rights are not licensed under this
+ Public License.
+
+ 3. To the extent possible, the Licensor waives any right to
+ collect royalties from You for the exercise of the Licensed
+ Rights, whether directly or through a collecting society
+ under any voluntary or waivable statutory or compulsory
+ licensing scheme. In all other cases the Licensor expressly
+ reserves any right to collect such royalties.
+
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the
+following conditions.
+
+ a. Attribution.
+
+ 1. If You Share the Licensed Material (including in modified
+ form), You must:
+
+ a. retain the following if it is supplied by the Licensor
+ with the Licensed Material:
+
+ i. identification of the creator(s) of the Licensed
+ Material and any others designated to receive
+ attribution, in any reasonable manner requested by
+ the Licensor (including by pseudonym if
+ designated);
+
+ ii. a copyright notice;
+
+ iii. a notice that refers to this Public License;
+
+ iv. a notice that refers to the disclaimer of
+ warranties;
+
+ v. a URI or hyperlink to the Licensed Material to the
+ extent reasonably practicable;
+
+ b. indicate if You modified the Licensed Material and
+ retain an indication of any previous modifications; and
+
+ c. indicate the Licensed Material is licensed under this
+ Public License, and include the text of, or the URI or
+ hyperlink to, this Public License.
+
+ 2. You may satisfy the conditions in Section 3(a)(1) in any
+ reasonable manner based on the medium, means, and context in
+ which You Share the Licensed Material. For example, it may be
+ reasonable to satisfy the conditions by providing a URI or
+ hyperlink to a resource that includes the required
+ information.
+
+ 3. If requested by the Licensor, You must remove any of the
+ information required by Section 3(a)(1)(A) to the extent
+ reasonably practicable.
+
+ 4. If You Share Adapted Material You produce, the Adapter's
+ License You apply must not prevent recipients of the Adapted
+ Material from complying with this Public License.
+
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that
+apply to Your use of the Licensed Material:
+
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+ to extract, reuse, reproduce, and Share all or a substantial
+ portion of the contents of the database;
+
+ b. if You include all or a substantial portion of the database
+ contents in a database in which You have Sui Generis Database
+ Rights, then the database in which You have Sui Generis Database
+ Rights (but not its individual contents) is Adapted Material; and
+
+ c. You must comply with the conditions in Section 3(a) if You Share
+ all or a substantial portion of the contents of the database.
+
+For the avoidance of doubt, this Section 4 supplements and does not
+replace Your obligations under this Public License where the Licensed
+Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+
+ c. The disclaimer of warranties and limitation of liability provided
+ above shall be interpreted in a manner that, to the extent
+ possible, most closely approximates an absolute disclaimer and
+ waiver of all liability.
+
+
+Section 6 -- Term and Termination.
+
+ a. This Public License applies for the term of the Copyright and
+ Similar Rights licensed here. However, if You fail to comply with
+ this Public License, then Your rights under this Public License
+ terminate automatically.
+
+ b. Where Your right to use the Licensed Material has terminated under
+ Section 6(a), it reinstates:
+
+ 1. automatically as of the date the violation is cured, provided
+ it is cured within 30 days of Your discovery of the
+ violation; or
+
+ 2. upon express reinstatement by the Licensor.
+
+ For the avoidance of doubt, this Section 6(b) does not affect any
+ right the Licensor may have to seek remedies for Your violations
+ of this Public License.
+
+ c. For the avoidance of doubt, the Licensor may also offer the
+ Licensed Material under separate terms or conditions or stop
+ distributing the Licensed Material at any time; however, doing so
+ will not terminate this Public License.
+
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+ License.
+
+
+Section 7 -- Other Terms and Conditions.
+
+ a. The Licensor shall not be bound by any additional or different
+ terms or conditions communicated by You unless expressly agreed.
+
+ b. Any arrangements, understandings, or agreements regarding the
+ Licensed Material not stated herein are separate from and
+ independent of the terms and conditions of this Public License.
+
+
+Section 8 -- Interpretation.
+
+ a. For the avoidance of doubt, this Public License does not, and
+ shall not be interpreted to, reduce, limit, restrict, or impose
+ conditions on any use of the Licensed Material that could lawfully
+ be made without permission under this Public License.
+
+ b. To the extent possible, if any provision of this Public License is
+ deemed unenforceable, it shall be automatically reformed to the
+ minimum extent necessary to make it enforceable. If the provision
+ cannot be reformed, it shall be severed from this Public License
+ without affecting the enforceability of the remaining terms and
+ conditions.
+
+ c. No term or condition of this Public License will be waived and no
+ failure to comply consented to unless expressly agreed to by the
+ Licensor.
+
+ d. Nothing in this Public License constitutes or may be interpreted
+ as a limitation upon, or waiver of, any privileges and immunities
+ that apply to the Licensor or You, including from the legal
+ processes of any jurisdiction or authority.
+
+
+=======================================================================
+
+Creative Commons is not a party to its public
+licenses. Notwithstanding, Creative Commons may elect to apply one of
+its public licenses to material it publishes and in those instances
+will be considered the “Licensor.” The text of the Creative Commons
+public licenses is dedicated to the public domain under the CC0 Public
+Domain Dedication. Except for the limited purpose of indicating that
+material is shared under a Creative Commons public license or as
+otherwise permitted by the Creative Commons policies published at
+creativecommons.org/policies, Creative Commons does not authorize the
+use of the trademark "Creative Commons" or any other trademark or logo
+of Creative Commons without its prior written consent including,
+without limitation, in connection with any unauthorized modifications
+to any of its public licenses or any other arrangements,
+understandings, or agreements concerning use of licensed material. For
+the avoidance of doubt, this paragraph does not form part of the
+public licenses.
+
+Creative Commons may be contacted at creativecommons.org.
diff --git a/README.md b/README.md
index 0f62012..cab2fe9 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,38 @@
-# project.lecture-wasm
-A project repository to test WASM compatibility and limitations for QuantEcon Lectures
+# QuantEcon WASM project
+
+This repository contains a subset of the [lecture-python-intro](https://intro.quantecon.org/intro.html).
+
+This project is powered by Pyodide kernel which allows us to run the lectures in the browser without
+any installaion.
+
+## Development
+
+The script `update_lectures.py` is used to fetch the latest version of lectures from the
+[wasm branch of lecture-python-intro series](https://github.com/QuantEcon/lecture-python-intro/tree/wasm).
+
+In order to build and test the project locally, please install the required libraries using
+```
+pip install -r requirements.txt
+```
+
+And run a local server using
+```
+teachbooks serve
+```
+
+To stop the server use:
+```
+teachbooks serve stop
+```
+
+### Update a lecture?
+
+In order to update any lecture, it's recommended to update the same lecture in the
+[wasm branch of lecture-python-intro series](https://github.com/QuantEcon/lecture-python-intro/tree/wasm) and
+run the script
+```
+python update_lectures.py
+```
+
+This allows us the keep all the lectures up-to-date in a single place and keep this repository a mirror of the
+main repository.
diff --git a/_config_copy.yml b/_config_copy.yml
new file mode 100644
index 0000000..32e949a
--- /dev/null
+++ b/_config_copy.yml
@@ -0,0 +1,83 @@
+author: QuantEcon team
+
+execute:
+ execute_notebooks: "off"
+
+only_build_toc_files: true
+
+html:
+ favicon : "figures/favicon.ico"
+ baseurl : "https://quantecon.org/"
+
+sphinx:
+ config:
+ html_js_files:
+ - https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js
+ thebe_config:
+ use_thebe_lite: true
+ exclude_patterns: ["**/_*.yml", "**/*.md", "**/*.ipynb"]
+ html_theme_options:
+ logo:
+ text: QuantEcon Intro Lectures
+ image_light: figures/qe-logo.png
+ image_dark: figures/qe-logo.png
+ authors:
+ - name: Thomas J. Sargent
+ url: http://www.tomsargent.com/
+ - name: John Stachurski
+ url: https://johnstachurski.net/
+ header_organisation_url: https://quantecon.org
+ header_organisation: QuantEcon
+ repository_url: https://github.com/QuantEcon/lecture-python-advanced.myst
+ nb_repository_url: https://github.com/QuantEcon/lecture-python-advanced.notebooks
+ twitter: quantecon
+ twitter_logo_url: https://assets.quantecon.org/img/qe-twitter-logo.png
+ og_logo_url: https://assets.quantecon.org/img/qe-og-logo.png
+ description: This website presents a set of lectures on advanced quantitative economic modeling, designed and written by Thomas J. Sargent and John Stachurski.
+ keywords: Python, QuantEcon, Quantitative Economics, Economics, Sloan, Alfred P. Sloan Foundation, Tom J. Sargent, John Stachurski
+ analytics:
+ google_analytics_id: G-KZLV7PM9LL
+ launch_buttons:
+ thebe: true
+ #colab_url : https://colab.research.google.com
+ mathjax3_config:
+ tex:
+ macros:
+ "argmax": "arg\\,max"
+ "argmin": "arg\\,min"
+ "col": "col"
+ "Span": "span"
+ "epsilon": "\\varepsilon"
+ "EE": "\\mathbb{E}"
+ "PP": "\\mathbb{P}"
+ "RR": "\\mathbb{R}"
+ "NN": "\\mathbb{N}"
+ "ZZ": "\\mathbb{Z}"
+ "aA": "\\mathcal{A}"
+ "bB": "\\mathcal{B}"
+ "cC": "\\mathcal{C}"
+ "dD": "\\mathcal{D}"
+ "eE": "\\mathcal{E}"
+ "fF": "\\mathcal{F}"
+ "gG": "\\mathcal{G}"
+ "hH": "\\mathcal{H}"
+ html_show_copyright: false
+ html_last_updated_fmt: '%B %-d, %Y'
+ html_static_path: ["figures"] # add folders that contain files that need to be included, such as the location of the logo(s)
+ mathjax3_config:
+ chtml: {
+ mtextInheritFont: true # To typeset text within math prettier
+ }
+ extra_extensions:
+ - sphinx.ext.imgconverter
+ - jupyterbook_patches
+ - download_link_replacer
+ - sphinx.ext.extlinks
+ - sphinx_image_inverter
+ - sphinx_exercise
+ - sphinx_proof
+ - sphinx_tojupyter
+ - sphinx_reredirects
+
+bibtex_bibfiles:
+ - references.bib
diff --git a/book/_build/.doctrees/about.doctree b/book/_build/.doctrees/about.doctree
new file mode 100644
index 0000000..1a99427
Binary files /dev/null and b/book/_build/.doctrees/about.doctree differ
diff --git a/book/_build/.doctrees/ar1_processes.doctree b/book/_build/.doctrees/ar1_processes.doctree
new file mode 100644
index 0000000..d0fa151
Binary files /dev/null and b/book/_build/.doctrees/ar1_processes.doctree differ
diff --git a/book/_build/.doctrees/business_cycle.doctree b/book/_build/.doctrees/business_cycle.doctree
new file mode 100644
index 0000000..d977a70
Binary files /dev/null and b/book/_build/.doctrees/business_cycle.doctree differ
diff --git a/book/_build/.doctrees/cagan_adaptive.doctree b/book/_build/.doctrees/cagan_adaptive.doctree
new file mode 100644
index 0000000..01a8717
Binary files /dev/null and b/book/_build/.doctrees/cagan_adaptive.doctree differ
diff --git a/book/_build/.doctrees/cagan_ree.doctree b/book/_build/.doctrees/cagan_ree.doctree
new file mode 100644
index 0000000..fff1cbe
Binary files /dev/null and b/book/_build/.doctrees/cagan_ree.doctree differ
diff --git a/book/_build/.doctrees/cobweb.doctree b/book/_build/.doctrees/cobweb.doctree
new file mode 100644
index 0000000..3226246
Binary files /dev/null and b/book/_build/.doctrees/cobweb.doctree differ
diff --git a/book/_build/.doctrees/commod_price.doctree b/book/_build/.doctrees/commod_price.doctree
new file mode 100644
index 0000000..c600df6
Binary files /dev/null and b/book/_build/.doctrees/commod_price.doctree differ
diff --git a/book/_build/.doctrees/complex_and_trig.doctree b/book/_build/.doctrees/complex_and_trig.doctree
new file mode 100644
index 0000000..f3cbef6
Binary files /dev/null and b/book/_build/.doctrees/complex_and_trig.doctree differ
diff --git a/book/_build/.doctrees/cons_smooth.doctree b/book/_build/.doctrees/cons_smooth.doctree
new file mode 100644
index 0000000..ea353b1
Binary files /dev/null and b/book/_build/.doctrees/cons_smooth.doctree differ
diff --git a/book/_build/.doctrees/eigen_I.doctree b/book/_build/.doctrees/eigen_I.doctree
new file mode 100644
index 0000000..e218a96
Binary files /dev/null and b/book/_build/.doctrees/eigen_I.doctree differ
diff --git a/book/_build/.doctrees/eigen_II.doctree b/book/_build/.doctrees/eigen_II.doctree
new file mode 100644
index 0000000..f43f923
Binary files /dev/null and b/book/_build/.doctrees/eigen_II.doctree differ
diff --git a/book/_build/.doctrees/environment.pickle b/book/_build/.doctrees/environment.pickle
new file mode 100644
index 0000000..b4f45fd
Binary files /dev/null and b/book/_build/.doctrees/environment.pickle differ
diff --git a/book/_build/.doctrees/equalizing_difference.doctree b/book/_build/.doctrees/equalizing_difference.doctree
new file mode 100644
index 0000000..8970dcb
Binary files /dev/null and b/book/_build/.doctrees/equalizing_difference.doctree differ
diff --git a/book/_build/.doctrees/french_rev.doctree b/book/_build/.doctrees/french_rev.doctree
new file mode 100644
index 0000000..85d31b5
Binary files /dev/null and b/book/_build/.doctrees/french_rev.doctree differ
diff --git a/book/_build/.doctrees/geom_series.doctree b/book/_build/.doctrees/geom_series.doctree
new file mode 100644
index 0000000..bd50a7f
Binary files /dev/null and b/book/_build/.doctrees/geom_series.doctree differ
diff --git a/book/_build/.doctrees/greek_square.doctree b/book/_build/.doctrees/greek_square.doctree
new file mode 100644
index 0000000..b14b53c
Binary files /dev/null and b/book/_build/.doctrees/greek_square.doctree differ
diff --git a/book/_build/.doctrees/heavy_tails.doctree b/book/_build/.doctrees/heavy_tails.doctree
new file mode 100644
index 0000000..008b184
Binary files /dev/null and b/book/_build/.doctrees/heavy_tails.doctree differ
diff --git a/book/_build/.doctrees/inequality.doctree b/book/_build/.doctrees/inequality.doctree
new file mode 100644
index 0000000..98640ce
Binary files /dev/null and b/book/_build/.doctrees/inequality.doctree differ
diff --git a/book/_build/.doctrees/inflation_history.doctree b/book/_build/.doctrees/inflation_history.doctree
new file mode 100644
index 0000000..770ad76
Binary files /dev/null and b/book/_build/.doctrees/inflation_history.doctree differ
diff --git a/book/_build/.doctrees/input_output.doctree b/book/_build/.doctrees/input_output.doctree
new file mode 100644
index 0000000..2093a63
Binary files /dev/null and b/book/_build/.doctrees/input_output.doctree differ
diff --git a/book/_build/.doctrees/intro.doctree b/book/_build/.doctrees/intro.doctree
new file mode 100644
index 0000000..69a4c34
Binary files /dev/null and b/book/_build/.doctrees/intro.doctree differ
diff --git a/book/_build/.doctrees/intro_supply_demand.doctree b/book/_build/.doctrees/intro_supply_demand.doctree
new file mode 100644
index 0000000..e993adc
Binary files /dev/null and b/book/_build/.doctrees/intro_supply_demand.doctree differ
diff --git a/book/_build/.doctrees/laffer_adaptive.doctree b/book/_build/.doctrees/laffer_adaptive.doctree
new file mode 100644
index 0000000..282b293
Binary files /dev/null and b/book/_build/.doctrees/laffer_adaptive.doctree differ
diff --git a/book/_build/.doctrees/lake_model.doctree b/book/_build/.doctrees/lake_model.doctree
new file mode 100644
index 0000000..16372f4
Binary files /dev/null and b/book/_build/.doctrees/lake_model.doctree differ
diff --git a/book/_build/.doctrees/linear_equations.doctree b/book/_build/.doctrees/linear_equations.doctree
new file mode 100644
index 0000000..ba1e8df
Binary files /dev/null and b/book/_build/.doctrees/linear_equations.doctree differ
diff --git a/book/_build/.doctrees/lln_clt.doctree b/book/_build/.doctrees/lln_clt.doctree
new file mode 100644
index 0000000..9ab7525
Binary files /dev/null and b/book/_build/.doctrees/lln_clt.doctree differ
diff --git a/book/_build/.doctrees/long_run_growth.doctree b/book/_build/.doctrees/long_run_growth.doctree
new file mode 100644
index 0000000..aaf9cee
Binary files /dev/null and b/book/_build/.doctrees/long_run_growth.doctree differ
diff --git a/book/_build/.doctrees/lp_intro.doctree b/book/_build/.doctrees/lp_intro.doctree
new file mode 100644
index 0000000..7e5cd32
Binary files /dev/null and b/book/_build/.doctrees/lp_intro.doctree differ
diff --git a/book/_build/.doctrees/markov_chains_I.doctree b/book/_build/.doctrees/markov_chains_I.doctree
new file mode 100644
index 0000000..cbf2bc2
Binary files /dev/null and b/book/_build/.doctrees/markov_chains_I.doctree differ
diff --git a/book/_build/.doctrees/markov_chains_II.doctree b/book/_build/.doctrees/markov_chains_II.doctree
new file mode 100644
index 0000000..23c4ad0
Binary files /dev/null and b/book/_build/.doctrees/markov_chains_II.doctree differ
diff --git a/book/_build/.doctrees/mle.doctree b/book/_build/.doctrees/mle.doctree
new file mode 100644
index 0000000..b81541f
Binary files /dev/null and b/book/_build/.doctrees/mle.doctree differ
diff --git a/book/_build/.doctrees/money_inflation.doctree b/book/_build/.doctrees/money_inflation.doctree
new file mode 100644
index 0000000..395e7d1
Binary files /dev/null and b/book/_build/.doctrees/money_inflation.doctree differ
diff --git a/book/_build/.doctrees/money_inflation_nonlinear.doctree b/book/_build/.doctrees/money_inflation_nonlinear.doctree
new file mode 100644
index 0000000..3d24a04
Binary files /dev/null and b/book/_build/.doctrees/money_inflation_nonlinear.doctree differ
diff --git a/book/_build/.doctrees/monte_carlo.doctree b/book/_build/.doctrees/monte_carlo.doctree
new file mode 100644
index 0000000..79afa65
Binary files /dev/null and b/book/_build/.doctrees/monte_carlo.doctree differ
diff --git a/book/_build/.doctrees/networks.doctree b/book/_build/.doctrees/networks.doctree
new file mode 100644
index 0000000..0695bb7
Binary files /dev/null and b/book/_build/.doctrees/networks.doctree differ
diff --git a/book/_build/.doctrees/olg.doctree b/book/_build/.doctrees/olg.doctree
new file mode 100644
index 0000000..fa88655
Binary files /dev/null and b/book/_build/.doctrees/olg.doctree differ
diff --git a/book/_build/.doctrees/prob_dist.doctree b/book/_build/.doctrees/prob_dist.doctree
new file mode 100644
index 0000000..258abc9
Binary files /dev/null and b/book/_build/.doctrees/prob_dist.doctree differ
diff --git a/book/_build/.doctrees/pv.doctree b/book/_build/.doctrees/pv.doctree
new file mode 100644
index 0000000..2f7d791
Binary files /dev/null and b/book/_build/.doctrees/pv.doctree differ
diff --git a/book/_build/.doctrees/scalar_dynam.doctree b/book/_build/.doctrees/scalar_dynam.doctree
new file mode 100644
index 0000000..53db913
Binary files /dev/null and b/book/_build/.doctrees/scalar_dynam.doctree differ
diff --git a/book/_build/.doctrees/schelling.doctree b/book/_build/.doctrees/schelling.doctree
new file mode 100644
index 0000000..1ce294b
Binary files /dev/null and b/book/_build/.doctrees/schelling.doctree differ
diff --git a/book/_build/.doctrees/short_path.doctree b/book/_build/.doctrees/short_path.doctree
new file mode 100644
index 0000000..851c2da
Binary files /dev/null and b/book/_build/.doctrees/short_path.doctree differ
diff --git a/book/_build/.doctrees/simple_linear_regression.doctree b/book/_build/.doctrees/simple_linear_regression.doctree
new file mode 100644
index 0000000..ace49a0
Binary files /dev/null and b/book/_build/.doctrees/simple_linear_regression.doctree differ
diff --git a/book/_build/.doctrees/solow.doctree b/book/_build/.doctrees/solow.doctree
new file mode 100644
index 0000000..5e4194d
Binary files /dev/null and b/book/_build/.doctrees/solow.doctree differ
diff --git a/book/_build/.doctrees/status.doctree b/book/_build/.doctrees/status.doctree
new file mode 100644
index 0000000..4bce960
Binary files /dev/null and b/book/_build/.doctrees/status.doctree differ
diff --git a/book/_build/.doctrees/supply_demand_heterogeneity.doctree b/book/_build/.doctrees/supply_demand_heterogeneity.doctree
new file mode 100644
index 0000000..871387e
Binary files /dev/null and b/book/_build/.doctrees/supply_demand_heterogeneity.doctree differ
diff --git a/book/_build/.doctrees/supply_demand_multiple_goods.doctree b/book/_build/.doctrees/supply_demand_multiple_goods.doctree
new file mode 100644
index 0000000..32b9bd4
Binary files /dev/null and b/book/_build/.doctrees/supply_demand_multiple_goods.doctree differ
diff --git a/book/_build/.doctrees/time_series_with_matrices.doctree b/book/_build/.doctrees/time_series_with_matrices.doctree
new file mode 100644
index 0000000..5b016f9
Binary files /dev/null and b/book/_build/.doctrees/time_series_with_matrices.doctree differ
diff --git a/book/_build/.doctrees/troubleshooting.doctree b/book/_build/.doctrees/troubleshooting.doctree
new file mode 100644
index 0000000..ce2ea8f
Binary files /dev/null and b/book/_build/.doctrees/troubleshooting.doctree differ
diff --git a/book/_build/.doctrees/unpleasant.doctree b/book/_build/.doctrees/unpleasant.doctree
new file mode 100644
index 0000000..3a6657a
Binary files /dev/null and b/book/_build/.doctrees/unpleasant.doctree differ
diff --git a/book/_build/.doctrees/zreferences.doctree b/book/_build/.doctrees/zreferences.doctree
new file mode 100644
index 0000000..f0aa350
Binary files /dev/null and b/book/_build/.doctrees/zreferences.doctree differ
diff --git a/book/_build/html/.buildinfo b/book/_build/html/.buildinfo
new file mode 100644
index 0000000..53f3fb3
--- /dev/null
+++ b/book/_build/html/.buildinfo
@@ -0,0 +1,4 @@
+# Sphinx build info version 1
+# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
+config: 50cb353efd1d91078461a3644c2c991f
+tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/book/_build/html/_images/Hamilton.png b/book/_build/html/_images/Hamilton.png
new file mode 100644
index 0000000..caeccf2
Binary files /dev/null and b/book/_build/html/_images/Hamilton.png differ
diff --git a/book/_build/html/_images/Irre_1.png b/book/_build/html/_images/Irre_1.png
new file mode 100644
index 0000000..5510b4d
Binary files /dev/null and b/book/_build/html/_images/Irre_1.png differ
diff --git a/book/_build/html/_images/Irre_2.png b/book/_build/html/_images/Irre_2.png
new file mode 100644
index 0000000..2661a24
Binary files /dev/null and b/book/_build/html/_images/Irre_2.png differ
diff --git a/book/_build/html/_images/Temple.png b/book/_build/html/_images/Temple.png
new file mode 100644
index 0000000..41f07a0
Binary files /dev/null and b/book/_build/html/_images/Temple.png differ
diff --git a/book/_build/html/_images/example4.png b/book/_build/html/_images/example4.png
new file mode 100644
index 0000000..a7844b4
Binary files /dev/null and b/book/_build/html/_images/example4.png differ
diff --git a/book/_build/html/_images/graph.png b/book/_build/html/_images/graph.png
new file mode 100644
index 0000000..2b451a4
Binary files /dev/null and b/book/_build/html/_images/graph.png differ
diff --git a/book/_build/html/_images/graph2.png b/book/_build/html/_images/graph2.png
new file mode 100644
index 0000000..7bc5a5d
Binary files /dev/null and b/book/_build/html/_images/graph2.png differ
diff --git a/book/_build/html/_images/graph3.png b/book/_build/html/_images/graph3.png
new file mode 100644
index 0000000..13b2463
Binary files /dev/null and b/book/_build/html/_images/graph3.png differ
diff --git a/book/_build/html/_images/graph4.png b/book/_build/html/_images/graph4.png
new file mode 100644
index 0000000..b817225
Binary files /dev/null and b/book/_build/html/_images/graph4.png differ
diff --git a/book/_build/html/_images/lake_model_worker.png b/book/_build/html/_images/lake_model_worker.png
new file mode 100644
index 0000000..802a23c
Binary files /dev/null and b/book/_build/html/_images/lake_model_worker.png differ
diff --git a/content/lectures/_static/lecture_specific/troubleshooting/launch.png b/book/_build/html/_images/launch.png
similarity index 100%
rename from content/lectures/_static/lecture_specific/troubleshooting/launch.png
rename to book/_build/html/_images/launch.png
diff --git a/book/_build/html/_images/mc.png b/book/_build/html/_images/mc.png
new file mode 100644
index 0000000..caeccf2
Binary files /dev/null and b/book/_build/html/_images/mc.png differ
diff --git a/book/_build/html/_images/poverty_trap_1.png b/book/_build/html/_images/poverty_trap_1.png
new file mode 100644
index 0000000..e3bda2a
Binary files /dev/null and b/book/_build/html/_images/poverty_trap_1.png differ
diff --git a/book/_build/html/_images/poverty_trap_2.png b/book/_build/html/_images/poverty_trap_2.png
new file mode 100644
index 0000000..71f2d31
Binary files /dev/null and b/book/_build/html/_images/poverty_trap_2.png differ
diff --git a/book/_build/html/_images/properties.png b/book/_build/html/_images/properties.png
new file mode 100644
index 0000000..7098688
Binary files /dev/null and b/book/_build/html/_images/properties.png differ
diff --git a/book/_build/html/_images/tooze_ch1_graph.png b/book/_build/html/_images/tooze_ch1_graph.png
new file mode 100644
index 0000000..3ae6891
Binary files /dev/null and b/book/_build/html/_images/tooze_ch1_graph.png differ
diff --git a/book/_build/html/_images/weighted.png b/book/_build/html/_images/weighted.png
new file mode 100644
index 0000000..5510b4d
Binary files /dev/null and b/book/_build/html/_images/weighted.png differ
diff --git a/book/_build/html/_sources/about.md b/book/_build/html/_sources/about.md
new file mode 100644
index 0000000..ac8c6f3
--- /dev/null
+++ b/book/_build/html/_sources/about.md
@@ -0,0 +1,75 @@
+# About These Lectures
+
+
+## About
+
+This lecture series introduces quantitative economics using elementary
+mathematics and statistics plus computer code written in
+[Python](https://www.python.org/).
+
+The lectures emphasize simulation and visualization through code as a way to
+convey ideas, rather than focusing on mathematical details.
+
+Although the presentation is quite novel, the ideas are rather foundational.
+
+We emphasize the deep and fundamental importance of economic theory, as well
+as the value of analyzing data and understanding stylized facts.
+
+The lectures can be used for university courses, self-study, reading groups or
+workshops.
+
+Researchers and policy professionals might also find some parts of the series
+valuable for their work.
+
+We hope the lectures will be of interest to students of economics
+who want to learn both economics and computing, as well as students from
+fields such as computer science and engineering who are curious about
+economics.
+
+## Level
+
+The lecture series is aimed at undergraduate students.
+
+The level of the lectures varies from truly introductory (suitable for first
+year undergraduates or even high school students) to more intermediate.
+
+The
+more intermediate lectures require comfort with linear algebra and some
+mathematical maturity (e.g., calmly reading theorems and trying to understand
+their meaning).
+
+In general, easier lectures occur earlier in the lecture
+series and harder lectures occur later.
+
+We assume that readers have covered the easier parts of the QuantEcon lecture
+series [on Python
+programming](https://python-programming.quantecon.org/intro.html).
+
+In
+particular, readers should be familiar with basic Python syntax including
+Python functions. Knowledge of classes and Matplotlib will be beneficial but
+not essential.
+
+## Credits
+
+In building this lecture series, we had invaluable assistance from research
+assistants at QuantEcon, as well as our QuantEcon colleagues. Without their
+help this series would not have been possible.
+
+In particular, we sincerely thank and give credit to
+
+- [Aakash Gupta](https://github.com/AakashGfude)
+- [Shu Hu](https://github.com/shlff)
+- Jiacheng Li
+- [Jiarui Zhang](https://github.com/Jiarui-ZH)
+- [Smit Lunagariya](https://github.com/Smit-create)
+- [Maanasee Sharma](https://github.com/maanasee)
+- [Matthew McKay](https://github.com/mmcky)
+- [Margaret Beisenbek](https://github.com/mbek0605)
+- [Phoebe Grosser](https://github.com/pgrosser1)
+- [Longye Tian](https://github.com/longye-tian)
+- [Humphrey Yang](https://github.com/HumphreyYang)
+- [Sylvia Zhao](https://github.com/SylviaZhaooo)
+
+We also thank Noritaka Kudoh for encouraging us to start this project and providing thoughtful suggestions.
+
diff --git a/book/_build/html/_sources/ar1_processes.ipynb b/book/_build/html/_sources/ar1_processes.ipynb
new file mode 100644
index 0000000..d62f8a1
--- /dev/null
+++ b/book/_build/html/_sources/ar1_processes.ipynb
@@ -0,0 +1,830 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "06599583",
+ "metadata": {},
+ "source": [
+ "(ar1)=\n",
+ "```{raw} html\n",
+ "
\n",
+ "```\n",
+ "\n",
+ "(ar1_processes)=\n",
+ "# AR(1) Processes\n",
+ "\n",
+ "```{index} single: Autoregressive processes\n",
+ "```\n",
+ "\n",
+ "## Overview\n",
+ "\n",
+ "In this lecture we are going to study a very simple class of stochastic\n",
+ "models called AR(1) processes.\n",
+ "\n",
+ "These simple models are used again and again in economic research to represent the dynamics of series such as\n",
+ "\n",
+ "* labor income\n",
+ "* dividends\n",
+ "* productivity, etc.\n",
+ "\n",
+ "We are going to study AR(1) processes partly because they are useful and\n",
+ "partly because they help us understand important concepts. \n",
+ "\n",
+ "Let's start with some imports:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "731a6973",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.rcParams[\"figure.figsize\"] = (11, 5) #set default figure size"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ec4c9d96",
+ "metadata": {},
+ "source": [
+ "## The AR(1) model\n",
+ "\n",
+ "The **AR(1) model** (autoregressive model of order 1) takes the form\n",
+ "\n",
+ "```{math}\n",
+ ":label: can_ar1\n",
+ "\n",
+ "X_{t+1} = a X_t + b + c W_{t+1}\n",
+ "```\n",
+ "\n",
+ "where $a, b, c$ are scalar-valued parameters \n",
+ "\n",
+ "(Equation {eq}`can_ar1` is sometimes called a **stochastic difference equation**.)\n",
+ "\n",
+ "```{prf:example}\n",
+ ":label: ar1_ex_ar\n",
+ "\n",
+ "For example, $X_t$ might be \n",
+ "\n",
+ "* the log of labor income for a given household, or\n",
+ "* the log of money demand in a given economy.\n",
+ "\n",
+ "In either case, {eq}`can_ar1` shows that the current value evolves as a linear function\n",
+ "of the previous value and an IID shock $W_{t+1}$.\n",
+ "\n",
+ "(We use $t+1$ for the subscript of $W_{t+1}$ because this random variable is not\n",
+ "observed at time $t$.)\n",
+ "```\n",
+ "\n",
+ "The specification {eq}`can_ar1` generates a time series $\\{ X_t\\}$ as soon as we\n",
+ "specify an initial condition $X_0$.\n",
+ "\n",
+ "To make things even simpler, we will assume that\n",
+ "\n",
+ "* the process $\\{ W_t \\}$ is {ref}`IID ` and standard normal,\n",
+ "* the initial condition $X_0$ is drawn from the normal distribution $N(\\mu_0, v_0)$ and\n",
+ "* the initial condition $X_0$ is independent of $\\{ W_t \\}$.\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "### Moving average representation\n",
+ "\n",
+ "Iterating backwards from time $t$, we obtain\n",
+ "\n",
+ "$$\n",
+ "X_t = a X_{t-1} + b + c W_t\n",
+ " = a^2 X_{t-2} + a b + a c W_{t-1} + b + c W_t\n",
+ " = a^3 X_{t-3} + a^2 b + a^2 c W_{t-2} + b + c W_t\n",
+ " = \\cdots\n",
+ "$$\n",
+ "\n",
+ "If we work all the way back to time zero, we get\n",
+ "\n",
+ "```{math}\n",
+ ":label: ar1_ma\n",
+ "\n",
+ "X_t = a^t X_0 + b \\sum_{j=0}^{t-1} a^j +\n",
+ " c \\sum_{j=0}^{t-1} a^j W_{t-j}\n",
+ "```\n",
+ "\n",
+ "Equation {eq}`ar1_ma` shows that $X_t$ is a well defined random variable, the value of which depends on\n",
+ "\n",
+ "* the parameters,\n",
+ "* the initial condition $X_0$ and\n",
+ "* the shocks $W_1, \\ldots W_t$ from time $t=1$ to the present.\n",
+ "\n",
+ "Throughout, the symbol $\\psi_t$ will be used to refer to the\n",
+ "density of this random variable $X_t$.\n",
+ "\n",
+ "### Distribution dynamics\n",
+ "\n",
+ "One of the nice things about this model is that it's so easy to trace out the sequence of distributions $\\{ \\psi_t \\}$ corresponding to the time\n",
+ "series $\\{ X_t\\}$.\n",
+ "\n",
+ "To see this, we first note that $X_t$ is normally distributed for each $t$.\n",
+ "\n",
+ "This is immediate from {eq}`ar1_ma`, since linear combinations of independent\n",
+ "normal random variables are normal.\n",
+ "\n",
+ "Given that $X_t$ is normally distributed, we will know the full distribution\n",
+ "$\\psi_t$ if we can pin down its first two [moments](https://en.wikipedia.org/wiki/Moment_(mathematics)).\n",
+ "\n",
+ "Let $\\mu_t$ and $v_t$ denote the mean and variance of $X_t$ respectively.\n",
+ "\n",
+ "We can pin down these values from {eq}`ar1_ma` or we can use the following\n",
+ "recursive expressions:\n",
+ "\n",
+ "```{math}\n",
+ ":label: dyn_tm\n",
+ "\n",
+ "\\mu_{t+1} = a \\mu_t + b\n",
+ "\\quad \\text{and} \\quad\n",
+ "v_{t+1} = a^2 v_t + c^2\n",
+ "```\n",
+ "\n",
+ "These expressions are obtained from {eq}`can_ar1` by taking, respectively, the expectation and variance of both sides of the equality.\n",
+ "\n",
+ "In calculating the second expression, we are using the fact that $X_t$\n",
+ "and $W_{t+1}$ are independent.\n",
+ "\n",
+ "(This follows from our assumptions and {eq}`ar1_ma`.)\n",
+ "\n",
+ "Given the dynamics in {eq}`ar1_ma` and initial conditions $\\mu_0,\n",
+ "v_0$, we obtain $\\mu_t, v_t$ and hence\n",
+ "\n",
+ "$$\n",
+ "\\psi_t = N(\\mu_t, v_t)\n",
+ "$$\n",
+ "\n",
+ "The following code uses these facts to track the sequence of marginal distributions $\\{ \\psi_t \\}$.\n",
+ "\n",
+ "The parameters are"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d5e587ea",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "a, b, c = 0.9, 0.1, 0.5\n",
+ "\n",
+ "mu, v = -3.0, 0.6 # initial conditions mu_0, v_0"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0da85415",
+ "metadata": {},
+ "source": [
+ "Here's the sequence of distributions:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e1a3f93d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from scipy.stats import norm\n",
+ "\n",
+ "sim_length = 10\n",
+ "grid = np.linspace(-5, 7, 120)\n",
+ "\n",
+ "fig, ax = plt.subplots()\n",
+ "\n",
+ "for t in range(sim_length):\n",
+ " mu = a * mu + b\n",
+ " v = a**2 * v + c**2\n",
+ " ax.plot(grid, norm.pdf(grid, loc=mu, scale=np.sqrt(v)),\n",
+ " label=f\"$\\psi_{t}$\",\n",
+ " alpha=0.7)\n",
+ "\n",
+ "ax.legend(bbox_to_anchor=[1.05,1],loc=2,borderaxespad=1)\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "92743b1e",
+ "metadata": {},
+ "source": [
+ "## Stationarity and asymptotic stability\n",
+ "\n",
+ "When we use models to study the real world, it is generally preferable that our\n",
+ "models have clear, sharp predictions.\n",
+ "\n",
+ "For dynamic problems, sharp predictions are related to stability.\n",
+ "\n",
+ "For example, if a dynamic model predicts that inflation always converges to some\n",
+ "kind of steady state, then the model gives a sharp prediction.\n",
+ "\n",
+ "(The prediction might be wrong, but even this is helpful, because we can judge the quality of the model.)\n",
+ "\n",
+ "Notice that, in the figure above, the sequence $\\{ \\psi_t \\}$ seems to be converging to a limiting distribution, suggesting some kind of stability.\n",
+ "\n",
+ "This is even clearer if we project forward further into the future:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1fbb6210",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plot_density_seq(ax, mu_0=-3.0, v_0=0.6, sim_length=40):\n",
+ " mu, v = mu_0, v_0\n",
+ " for t in range(sim_length):\n",
+ " mu = a * mu + b\n",
+ " v = a**2 * v + c**2\n",
+ " ax.plot(grid,\n",
+ " norm.pdf(grid, loc=mu, scale=np.sqrt(v)),\n",
+ " alpha=0.5)\n",
+ "\n",
+ "fig, ax = plt.subplots()\n",
+ "plot_density_seq(ax)\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0f644019",
+ "metadata": {},
+ "source": [
+ "Moreover, the limit does not depend on the initial condition.\n",
+ "\n",
+ "For example, this alternative density sequence also converges to the same limit."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8623820d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "plot_density_seq(ax, mu_0=4.0)\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "57c613de",
+ "metadata": {},
+ "source": [
+ "In fact it's easy to show that such convergence will occur, regardless of the initial condition, whenever $|a| < 1$.\n",
+ "\n",
+ "To see this, we just have to look at the dynamics of the first two moments, as\n",
+ "given in {eq}`dyn_tm`.\n",
+ "\n",
+ "When $|a| < 1$, these sequences converge to the respective limits\n",
+ "\n",
+ "```{math}\n",
+ ":label: mu_sig_star\n",
+ "\n",
+ "\\mu^* := \\frac{b}{1-a}\n",
+ "\\quad \\text{and} \\quad\n",
+ "v^* = \\frac{c^2}{1 - a^2}\n",
+ "```\n",
+ "\n",
+ "(See our {doc}`lecture on one dimensional dynamics ` for background on deterministic convergence.)\n",
+ "\n",
+ "Hence\n",
+ "\n",
+ "```{math}\n",
+ ":label: ar1_psi_star\n",
+ "\n",
+ "\\psi_t \\to \\psi^* = N(\\mu^*, v^*)\n",
+ "\\quad \\text{as }\n",
+ "t \\to \\infty\n",
+ "```\n",
+ "\n",
+ "We can confirm this is valid for the sequence above using the following code."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d352e207",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "plot_density_seq(ax, mu_0=4.0)\n",
+ "\n",
+ "mu_star = b / (1 - a)\n",
+ "std_star = np.sqrt(c**2 / (1 - a**2)) # square root of v_star\n",
+ "psi_star = norm.pdf(grid, loc=mu_star, scale=std_star)\n",
+ "ax.plot(grid, psi_star, 'k-', lw=2, label=\"$\\psi^*$\")\n",
+ "ax.legend()\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b07eb048",
+ "metadata": {},
+ "source": [
+ "As claimed, the sequence $\\{ \\psi_t \\}$ converges to $\\psi^*$.\n",
+ "\n",
+ "We see that, at least for these parameters, the AR(1) model has strong stability\n",
+ "properties.\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "### Stationary distributions\n",
+ "\n",
+ "Let's try to better understand the limiting distribution $\\psi^*$.\n",
+ "\n",
+ "A stationary distribution is a distribution that is a \"fixed point\" of the update rule for the AR(1) process.\n",
+ "\n",
+ "In other words, if $\\psi_t$ is stationary, then $\\psi_{t+j} = \\psi_t$ for all $j$ in $\\mathbb N$.\n",
+ "\n",
+ "A different way to put this, specialized to the current setting, is as follows: a density $\\psi$ on $\\mathbb R$ is **stationary** for the AR(1) process if\n",
+ "\n",
+ "$$\n",
+ "X_t \\sim \\psi\n",
+ "\\quad \\implies \\quad\n",
+ "a X_t + b + c W_{t+1} \\sim \\psi\n",
+ "$$\n",
+ "\n",
+ "The distribution $\\psi^*$ in {eq}`ar1_psi_star` has this property ---\n",
+ "checking this is an exercise.\n",
+ "\n",
+ "(Of course, we are assuming that $|a| < 1$ so that $\\psi^*$ is\n",
+ "well defined.)\n",
+ "\n",
+ "In fact, it can be shown that no other distribution on $\\mathbb R$ has this property.\n",
+ "\n",
+ "Thus, when $|a| < 1$, the AR(1) model has exactly one stationary density and that density is given by $\\psi^*$.\n",
+ "\n",
+ "## Ergodicity\n",
+ "\n",
+ "The concept of ergodicity is used in different ways by different authors.\n",
+ "\n",
+ "One way to understand it in the present setting is that a version of the law\n",
+ "of large numbers is valid for $\\{X_t\\}$, even though it is not IID.\n",
+ "\n",
+ "In particular, averages over time series converge to expectations under the\n",
+ "stationary distribution.\n",
+ "\n",
+ "Indeed, it can be proved that, whenever $|a| < 1$, we have\n",
+ "\n",
+ "```{math}\n",
+ ":label: ar1_ergo\n",
+ "\n",
+ "\\frac{1}{m} \\sum_{t = 1}^m h(X_t) \\to\n",
+ "\\int h(x) \\psi^*(x) dx\n",
+ " \\quad \\text{as } m \\to \\infty\n",
+ "```\n",
+ "\n",
+ "whenever the integral on the right hand side is finite and well defined.\n",
+ "\n",
+ "Notes:\n",
+ "\n",
+ "* In {eq}`ar1_ergo`, convergence holds with probability one.\n",
+ "* The textbook by {cite}`MeynTweedie2009` is a classic reference on ergodicity.\n",
+ "\n",
+ "```{prf:example}\n",
+ ":label: ar1_ex_id\n",
+ "\n",
+ "If we consider the identity function $h(x) = x$, we get\n",
+ "\n",
+ "$$\n",
+ "\\frac{1}{m} \\sum_{t = 1}^m X_t \\to\n",
+ "\\int x \\psi^*(x) dx\n",
+ " \\quad \\text{as } m \\to \\infty\n",
+ "$$\n",
+ "\n",
+ "In other words, the time series sample mean converges to the mean of the stationary distribution.\n",
+ "```\n",
+ "\n",
+ "Ergodicity is important for a range of reasons.\n",
+ "\n",
+ "For example, {eq}`ar1_ergo` can be used to test theory.\n",
+ "\n",
+ "In this equation, we can use observed data to evaluate the left hand side of {eq}`ar1_ergo`.\n",
+ "\n",
+ "And we can use a theoretical AR(1) model to calculate the right hand side.\n",
+ "\n",
+ "If $\\frac{1}{m} \\sum_{t = 1}^m X_t$ is not close to $\\psi^(x)$, even for many\n",
+ "observations, then our theory seems to be incorrect and we will need to revise\n",
+ "it.\n",
+ "\n",
+ "\n",
+ "## Exercises\n",
+ "\n",
+ "```{exercise}\n",
+ ":label: ar1p_ex1\n",
+ "\n",
+ "Let $k$ be a natural number.\n",
+ "\n",
+ "The $k$-th central moment of a random variable is defined as\n",
+ "\n",
+ "$$\n",
+ "M_k := \\mathbb E [ (X - \\mathbb E X )^k ]\n",
+ "$$\n",
+ "\n",
+ "When that random variable is $N(\\mu, \\sigma^2)$, it is known that\n",
+ "\n",
+ "$$\n",
+ "M_k =\n",
+ "\\begin{cases}\n",
+ " 0 & \\text{ if } k \\text{ is odd} \\\\\n",
+ " \\sigma^k (k-1)!! & \\text{ if } k \\text{ is even}\n",
+ "\\end{cases}\n",
+ "$$\n",
+ "\n",
+ "Here $n!!$ is the [double factorial](https://en.wikipedia.org/wiki/Double_factorial).\n",
+ "\n",
+ "According to {eq}`ar1_ergo`, we should have, for any $k \\in \\mathbb N$,\n",
+ "\n",
+ "$$\n",
+ "\\frac{1}{m} \\sum_{t = 1}^m\n",
+ " (X_t - \\mu^* )^k\n",
+ " \\approx M_k\n",
+ "$$\n",
+ "\n",
+ "when $m$ is large.\n",
+ "\n",
+ "Confirm this by simulation at a range of $k$ using the default parameters from the lecture.\n",
+ "```\n",
+ "\n",
+ "\n",
+ "```{solution-start} ar1p_ex1\n",
+ ":class: dropdown\n",
+ "```\n",
+ "\n",
+ "Here is one solution:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c5ccb412",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from numba import njit\n",
+ "from scipy.special import factorial2\n",
+ "\n",
+ "@njit\n",
+ "def sample_moments_ar1(k, m=100_000, mu_0=0.0, sigma_0=1.0, seed=1234):\n",
+ " np.random.seed(seed)\n",
+ " sample_sum = 0.0\n",
+ " x = mu_0 + sigma_0 * np.random.randn()\n",
+ " for t in range(m):\n",
+ " sample_sum += (x - mu_star)**k\n",
+ " x = a * x + b + c * np.random.randn()\n",
+ " return sample_sum / m\n",
+ "\n",
+ "def true_moments_ar1(k):\n",
+ " if k % 2 == 0:\n",
+ " return std_star**k * factorial2(k - 1)\n",
+ " else:\n",
+ " return 0\n",
+ "\n",
+ "k_vals = np.arange(6) + 1\n",
+ "sample_moments = np.empty_like(k_vals)\n",
+ "true_moments = np.empty_like(k_vals)\n",
+ "\n",
+ "for k_idx, k in enumerate(k_vals):\n",
+ " sample_moments[k_idx] = sample_moments_ar1(k)\n",
+ " true_moments[k_idx] = true_moments_ar1(k)\n",
+ "\n",
+ "fig, ax = plt.subplots()\n",
+ "ax.plot(k_vals, true_moments, label=\"true moments\")\n",
+ "ax.plot(k_vals, sample_moments, label=\"sample moments\")\n",
+ "ax.legend()\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0b8a62aa",
+ "metadata": {},
+ "source": [
+ "```{solution-end}\n",
+ "```\n",
+ "\n",
+ "\n",
+ "```{exercise}\n",
+ ":label: ar1p_ex2\n",
+ "\n",
+ "Write your own version of a one dimensional [kernel density\n",
+ "estimator](https://en.wikipedia.org/wiki/Kernel_density_estimation),\n",
+ "which estimates a density from a sample.\n",
+ "\n",
+ "Write it as a class that takes the data $X$ and bandwidth\n",
+ "$h$ when initialized and provides a method $f$ such that\n",
+ "\n",
+ "$$\n",
+ "f(x) = \\frac{1}{hn} \\sum_{i=1}^n\n",
+ "K \\left( \\frac{x-X_i}{h} \\right)\n",
+ "$$\n",
+ "\n",
+ "For $K$ use the Gaussian kernel ($K$ is the standard normal\n",
+ "density).\n",
+ "\n",
+ "Write the class so that the bandwidth defaults to Silverman’s rule (see\n",
+ "the “rule of thumb” discussion on [this\n",
+ "page](https://en.wikipedia.org/wiki/Kernel_density_estimation)). Test\n",
+ "the class you have written by going through the steps\n",
+ "\n",
+ "1. simulate data $X_1, \\ldots, X_n$ from distribution $\\phi$\n",
+ "1. plot the kernel density estimate over a suitable range\n",
+ "1. plot the density of $\\phi$ on the same figure\n",
+ "\n",
+ "for distributions $\\phi$ of the following types\n",
+ "\n",
+ "- [beta\n",
+ " distribution](https://en.wikipedia.org/wiki/Beta_distribution)\n",
+ " with $\\alpha = \\beta = 2$\n",
+ "- [beta\n",
+ " distribution](https://en.wikipedia.org/wiki/Beta_distribution)\n",
+ " with $\\alpha = 2$ and $\\beta = 5$\n",
+ "- [beta\n",
+ " distribution](https://en.wikipedia.org/wiki/Beta_distribution)\n",
+ " with $\\alpha = \\beta = 0.5$\n",
+ "\n",
+ "Use $n=500$.\n",
+ "\n",
+ "Make a comment on your results. (Do you think this is a good estimator\n",
+ "of these distributions?)\n",
+ "```\n",
+ "\n",
+ "\n",
+ "```{solution-start} ar1p_ex2\n",
+ ":class: dropdown\n",
+ "```\n",
+ "\n",
+ "Here is one solution:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a3755542",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "K = norm.pdf\n",
+ "\n",
+ "class KDE:\n",
+ "\n",
+ " def __init__(self, x_data, h=None):\n",
+ "\n",
+ " if h is None:\n",
+ " c = x_data.std()\n",
+ " n = len(x_data)\n",
+ " h = 1.06 * c * n**(-1/5)\n",
+ " self.h = h\n",
+ " self.x_data = x_data\n",
+ "\n",
+ " def f(self, x):\n",
+ " if np.isscalar(x):\n",
+ " return K((x - self.x_data) / self.h).mean() * (1/self.h)\n",
+ " else:\n",
+ " y = np.empty_like(x)\n",
+ " for i, x_val in enumerate(x):\n",
+ " y[i] = K((x_val - self.x_data) / self.h).mean() * (1/self.h)\n",
+ " return y"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2d67afef",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plot_kde(ϕ, x_min=-0.2, x_max=1.2):\n",
+ " x_data = ϕ.rvs(n)\n",
+ " kde = KDE(x_data)\n",
+ "\n",
+ " x_grid = np.linspace(-0.2, 1.2, 100)\n",
+ " fig, ax = plt.subplots()\n",
+ " ax.plot(x_grid, kde.f(x_grid), label=\"estimate\")\n",
+ " ax.plot(x_grid, ϕ.pdf(x_grid), label=\"true density\")\n",
+ " ax.legend()\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2b9be722",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from scipy.stats import beta\n",
+ "\n",
+ "n = 500\n",
+ "parameter_pairs= (2, 2), (2, 5), (0.5, 0.5)\n",
+ "for α, β in parameter_pairs:\n",
+ " plot_kde(beta(α, β))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d5822302",
+ "metadata": {},
+ "source": [
+ "We see that the kernel density estimator is effective when the underlying\n",
+ "distribution is smooth but less so otherwise.\n",
+ "\n",
+ "```{solution-end}\n",
+ "```\n",
+ "\n",
+ "\n",
+ "```{exercise}\n",
+ ":label: ar1p_ex3\n",
+ "\n",
+ "In the lecture we discussed the following fact: for the $AR(1)$ process\n",
+ "\n",
+ "$$\n",
+ "X_{t+1} = a X_t + b + c W_{t+1}\n",
+ "$$\n",
+ "\n",
+ "with $\\{ W_t \\}$ iid and standard normal,\n",
+ "\n",
+ "$$\n",
+ "\\psi_t = N(\\mu, s^2) \\implies \\psi_{t+1}\n",
+ "= N(a \\mu + b, a^2 s^2 + c^2)\n",
+ "$$\n",
+ "\n",
+ "Confirm this, at least approximately, by simulation. Let\n",
+ "\n",
+ "- $a = 0.9$\n",
+ "- $b = 0.0$\n",
+ "- $c = 0.1$\n",
+ "- $\\mu = -3$\n",
+ "- $s = 0.2$\n",
+ "\n",
+ "First, plot $\\psi_t$ and $\\psi_{t+1}$ using the true\n",
+ "distributions described above.\n",
+ "\n",
+ "Second, plot $\\psi_{t+1}$ on the same figure (in a different\n",
+ "color) as follows:\n",
+ "\n",
+ "1. Generate $n$ draws of $X_t$ from the $N(\\mu, s^2)$\n",
+ " distribution\n",
+ "1. Update them all using the rule\n",
+ " $X_{t+1} = a X_t + b + c W_{t+1}$\n",
+ "1. Use the resulting sample of $X_{t+1}$ values to produce a\n",
+ " density estimate via kernel density estimation.\n",
+ "\n",
+ "Try this for $n=2000$ and confirm that the\n",
+ "simulation based estimate of $\\psi_{t+1}$ does converge to the\n",
+ "theoretical distribution.\n",
+ "```\n",
+ "\n",
+ "```{solution-start} ar1p_ex3\n",
+ ":class: dropdown\n",
+ "```\n",
+ "\n",
+ "Here is our solution"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "380bd5b9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "a = 0.9\n",
+ "b = 0.0\n",
+ "c = 0.1\n",
+ "μ = -3\n",
+ "s = 0.2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8af1e3f3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "μ_next = a * μ + b\n",
+ "s_next = np.sqrt(a**2 * s**2 + c**2)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "409143ce",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ψ = lambda x: K((x - μ) / s)\n",
+ "ψ_next = lambda x: K((x - μ_next) / s_next)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8a203dd4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ψ = norm(μ, s)\n",
+ "ψ_next = norm(μ_next, s_next)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "aa021068",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "n = 2000\n",
+ "x_draws = ψ.rvs(n)\n",
+ "x_draws_next = a * x_draws + b + c * np.random.randn(n)\n",
+ "kde = KDE(x_draws_next)\n",
+ "\n",
+ "x_grid = np.linspace(μ - 1, μ + 1, 100)\n",
+ "fig, ax = plt.subplots()\n",
+ "\n",
+ "ax.plot(x_grid, ψ.pdf(x_grid), label=\"$\\psi_t$\")\n",
+ "ax.plot(x_grid, ψ_next.pdf(x_grid), label=\"$\\psi_{t+1}$\")\n",
+ "ax.plot(x_grid, kde.f(x_grid), label=\"estimate of $\\psi_{t+1}$\")\n",
+ "\n",
+ "ax.legend()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "65eb10a0",
+ "metadata": {},
+ "source": [
+ "The simulated distribution approximately coincides with the theoretical\n",
+ "distribution, as predicted.\n",
+ "\n",
+ "```{solution-end}\n",
+ "```"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst"
+ }
+ },
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "source_map": [
+ 10,
+ 43,
+ 47,
+ 163,
+ 167,
+ 171,
+ 189,
+ 209,
+ 222,
+ 228,
+ 232,
+ 263,
+ 274,
+ 409,
+ 443,
+ 501,
+ 525,
+ 538,
+ 545,
+ 602,
+ 610,
+ 615,
+ 620,
+ 625,
+ 640
+ ]
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/ar1_processes.md b/book/_build/html/_sources/ar1_processes.md
new file mode 100644
index 0000000..fe54d3d
--- /dev/null
+++ b/book/_build/html/_sources/ar1_processes.md
@@ -0,0 +1,646 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+kernelspec:
+ display_name: Python 3
+ language: python
+ name: python3
+---
+
+(ar1)=
+```{raw} html
+
+```
+
+(ar1_processes)=
+# AR(1) Processes
+
+```{index} single: Autoregressive processes
+```
+
+## Overview
+
+In this lecture we are going to study a very simple class of stochastic
+models called AR(1) processes.
+
+These simple models are used again and again in economic research to represent the dynamics of series such as
+
+* labor income
+* dividends
+* productivity, etc.
+
+We are going to study AR(1) processes partly because they are useful and
+partly because they help us understand important concepts.
+
+Let's start with some imports:
+
+```{code-cell} ipython
+import numpy as np
+import matplotlib.pyplot as plt
+plt.rcParams["figure.figsize"] = (11, 5) #set default figure size
+```
+
+## The AR(1) model
+
+The **AR(1) model** (autoregressive model of order 1) takes the form
+
+```{math}
+:label: can_ar1
+
+X_{t+1} = a X_t + b + c W_{t+1}
+```
+
+where $a, b, c$ are scalar-valued parameters
+
+(Equation {eq}`can_ar1` is sometimes called a **stochastic difference equation**.)
+
+```{prf:example}
+:label: ar1_ex_ar
+
+For example, $X_t$ might be
+
+* the log of labor income for a given household, or
+* the log of money demand in a given economy.
+
+In either case, {eq}`can_ar1` shows that the current value evolves as a linear function
+of the previous value and an IID shock $W_{t+1}$.
+
+(We use $t+1$ for the subscript of $W_{t+1}$ because this random variable is not
+observed at time $t$.)
+```
+
+The specification {eq}`can_ar1` generates a time series $\{ X_t\}$ as soon as we
+specify an initial condition $X_0$.
+
+To make things even simpler, we will assume that
+
+* the process $\{ W_t \}$ is {ref}`IID ` and standard normal,
+* the initial condition $X_0$ is drawn from the normal distribution $N(\mu_0, v_0)$ and
+* the initial condition $X_0$ is independent of $\{ W_t \}$.
+
+
+
+
+### Moving average representation
+
+Iterating backwards from time $t$, we obtain
+
+$$
+X_t = a X_{t-1} + b + c W_t
+ = a^2 X_{t-2} + a b + a c W_{t-1} + b + c W_t
+ = a^3 X_{t-3} + a^2 b + a^2 c W_{t-2} + b + c W_t
+ = \cdots
+$$
+
+If we work all the way back to time zero, we get
+
+```{math}
+:label: ar1_ma
+
+X_t = a^t X_0 + b \sum_{j=0}^{t-1} a^j +
+ c \sum_{j=0}^{t-1} a^j W_{t-j}
+```
+
+Equation {eq}`ar1_ma` shows that $X_t$ is a well defined random variable, the value of which depends on
+
+* the parameters,
+* the initial condition $X_0$ and
+* the shocks $W_1, \ldots W_t$ from time $t=1$ to the present.
+
+Throughout, the symbol $\psi_t$ will be used to refer to the
+density of this random variable $X_t$.
+
+### Distribution dynamics
+
+One of the nice things about this model is that it's so easy to trace out the sequence of distributions $\{ \psi_t \}$ corresponding to the time
+series $\{ X_t\}$.
+
+To see this, we first note that $X_t$ is normally distributed for each $t$.
+
+This is immediate from {eq}`ar1_ma`, since linear combinations of independent
+normal random variables are normal.
+
+Given that $X_t$ is normally distributed, we will know the full distribution
+$\psi_t$ if we can pin down its first two [moments](https://en.wikipedia.org/wiki/Moment_(mathematics)).
+
+Let $\mu_t$ and $v_t$ denote the mean and variance of $X_t$ respectively.
+
+We can pin down these values from {eq}`ar1_ma` or we can use the following
+recursive expressions:
+
+```{math}
+:label: dyn_tm
+
+\mu_{t+1} = a \mu_t + b
+\quad \text{and} \quad
+v_{t+1} = a^2 v_t + c^2
+```
+
+These expressions are obtained from {eq}`can_ar1` by taking, respectively, the expectation and variance of both sides of the equality.
+
+In calculating the second expression, we are using the fact that $X_t$
+and $W_{t+1}$ are independent.
+
+(This follows from our assumptions and {eq}`ar1_ma`.)
+
+Given the dynamics in {eq}`ar1_ma` and initial conditions $\mu_0,
+v_0$, we obtain $\mu_t, v_t$ and hence
+
+$$
+\psi_t = N(\mu_t, v_t)
+$$
+
+The following code uses these facts to track the sequence of marginal distributions $\{ \psi_t \}$.
+
+The parameters are
+
+```{code-cell} python3
+a, b, c = 0.9, 0.1, 0.5
+
+mu, v = -3.0, 0.6 # initial conditions mu_0, v_0
+```
+
+Here's the sequence of distributions:
+
+```{code-cell} python3
+from scipy.stats import norm
+
+sim_length = 10
+grid = np.linspace(-5, 7, 120)
+
+fig, ax = plt.subplots()
+
+for t in range(sim_length):
+ mu = a * mu + b
+ v = a**2 * v + c**2
+ ax.plot(grid, norm.pdf(grid, loc=mu, scale=np.sqrt(v)),
+ label=f"$\psi_{t}$",
+ alpha=0.7)
+
+ax.legend(bbox_to_anchor=[1.05,1],loc=2,borderaxespad=1)
+
+plt.show()
+```
+
+
+
+## Stationarity and asymptotic stability
+
+When we use models to study the real world, it is generally preferable that our
+models have clear, sharp predictions.
+
+For dynamic problems, sharp predictions are related to stability.
+
+For example, if a dynamic model predicts that inflation always converges to some
+kind of steady state, then the model gives a sharp prediction.
+
+(The prediction might be wrong, but even this is helpful, because we can judge the quality of the model.)
+
+Notice that, in the figure above, the sequence $\{ \psi_t \}$ seems to be converging to a limiting distribution, suggesting some kind of stability.
+
+This is even clearer if we project forward further into the future:
+
+```{code-cell} python3
+def plot_density_seq(ax, mu_0=-3.0, v_0=0.6, sim_length=40):
+ mu, v = mu_0, v_0
+ for t in range(sim_length):
+ mu = a * mu + b
+ v = a**2 * v + c**2
+ ax.plot(grid,
+ norm.pdf(grid, loc=mu, scale=np.sqrt(v)),
+ alpha=0.5)
+
+fig, ax = plt.subplots()
+plot_density_seq(ax)
+plt.show()
+```
+
+Moreover, the limit does not depend on the initial condition.
+
+For example, this alternative density sequence also converges to the same limit.
+
+```{code-cell} python3
+fig, ax = plt.subplots()
+plot_density_seq(ax, mu_0=4.0)
+plt.show()
+```
+
+In fact it's easy to show that such convergence will occur, regardless of the initial condition, whenever $|a| < 1$.
+
+To see this, we just have to look at the dynamics of the first two moments, as
+given in {eq}`dyn_tm`.
+
+When $|a| < 1$, these sequences converge to the respective limits
+
+```{math}
+:label: mu_sig_star
+
+\mu^* := \frac{b}{1-a}
+\quad \text{and} \quad
+v^* = \frac{c^2}{1 - a^2}
+```
+
+(See our {doc}`lecture on one dimensional dynamics ` for background on deterministic convergence.)
+
+Hence
+
+```{math}
+:label: ar1_psi_star
+
+\psi_t \to \psi^* = N(\mu^*, v^*)
+\quad \text{as }
+t \to \infty
+```
+
+We can confirm this is valid for the sequence above using the following code.
+
+```{code-cell} python3
+fig, ax = plt.subplots()
+plot_density_seq(ax, mu_0=4.0)
+
+mu_star = b / (1 - a)
+std_star = np.sqrt(c**2 / (1 - a**2)) # square root of v_star
+psi_star = norm.pdf(grid, loc=mu_star, scale=std_star)
+ax.plot(grid, psi_star, 'k-', lw=2, label="$\psi^*$")
+ax.legend()
+
+plt.show()
+```
+
+As claimed, the sequence $\{ \psi_t \}$ converges to $\psi^*$.
+
+We see that, at least for these parameters, the AR(1) model has strong stability
+properties.
+
+
+
+
+### Stationary distributions
+
+Let's try to better understand the limiting distribution $\psi^*$.
+
+A stationary distribution is a distribution that is a "fixed point" of the update rule for the AR(1) process.
+
+In other words, if $\psi_t$ is stationary, then $\psi_{t+j} = \psi_t$ for all $j$ in $\mathbb N$.
+
+A different way to put this, specialized to the current setting, is as follows: a density $\psi$ on $\mathbb R$ is **stationary** for the AR(1) process if
+
+$$
+X_t \sim \psi
+\quad \implies \quad
+a X_t + b + c W_{t+1} \sim \psi
+$$
+
+The distribution $\psi^*$ in {eq}`ar1_psi_star` has this property ---
+checking this is an exercise.
+
+(Of course, we are assuming that $|a| < 1$ so that $\psi^*$ is
+well defined.)
+
+In fact, it can be shown that no other distribution on $\mathbb R$ has this property.
+
+Thus, when $|a| < 1$, the AR(1) model has exactly one stationary density and that density is given by $\psi^*$.
+
+## Ergodicity
+
+The concept of ergodicity is used in different ways by different authors.
+
+One way to understand it in the present setting is that a version of the law
+of large numbers is valid for $\{X_t\}$, even though it is not IID.
+
+In particular, averages over time series converge to expectations under the
+stationary distribution.
+
+Indeed, it can be proved that, whenever $|a| < 1$, we have
+
+```{math}
+:label: ar1_ergo
+
+\frac{1}{m} \sum_{t = 1}^m h(X_t) \to
+\int h(x) \psi^*(x) dx
+ \quad \text{as } m \to \infty
+```
+
+whenever the integral on the right hand side is finite and well defined.
+
+Notes:
+
+* In {eq}`ar1_ergo`, convergence holds with probability one.
+* The textbook by {cite}`MeynTweedie2009` is a classic reference on ergodicity.
+
+```{prf:example}
+:label: ar1_ex_id
+
+If we consider the identity function $h(x) = x$, we get
+
+$$
+\frac{1}{m} \sum_{t = 1}^m X_t \to
+\int x \psi^*(x) dx
+ \quad \text{as } m \to \infty
+$$
+
+In other words, the time series sample mean converges to the mean of the stationary distribution.
+```
+
+Ergodicity is important for a range of reasons.
+
+For example, {eq}`ar1_ergo` can be used to test theory.
+
+In this equation, we can use observed data to evaluate the left hand side of {eq}`ar1_ergo`.
+
+And we can use a theoretical AR(1) model to calculate the right hand side.
+
+If $\frac{1}{m} \sum_{t = 1}^m X_t$ is not close to $\psi^(x)$, even for many
+observations, then our theory seems to be incorrect and we will need to revise
+it.
+
+
+## Exercises
+
+```{exercise}
+:label: ar1p_ex1
+
+Let $k$ be a natural number.
+
+The $k$-th central moment of a random variable is defined as
+
+$$
+M_k := \mathbb E [ (X - \mathbb E X )^k ]
+$$
+
+When that random variable is $N(\mu, \sigma^2)$, it is known that
+
+$$
+M_k =
+\begin{cases}
+ 0 & \text{ if } k \text{ is odd} \\
+ \sigma^k (k-1)!! & \text{ if } k \text{ is even}
+\end{cases}
+$$
+
+Here $n!!$ is the [double factorial](https://en.wikipedia.org/wiki/Double_factorial).
+
+According to {eq}`ar1_ergo`, we should have, for any $k \in \mathbb N$,
+
+$$
+\frac{1}{m} \sum_{t = 1}^m
+ (X_t - \mu^* )^k
+ \approx M_k
+$$
+
+when $m$ is large.
+
+Confirm this by simulation at a range of $k$ using the default parameters from the lecture.
+```
+
+
+```{solution-start} ar1p_ex1
+:class: dropdown
+```
+
+Here is one solution:
+
+```{code-cell} python3
+from numba import njit
+from scipy.special import factorial2
+
+@njit
+def sample_moments_ar1(k, m=100_000, mu_0=0.0, sigma_0=1.0, seed=1234):
+ np.random.seed(seed)
+ sample_sum = 0.0
+ x = mu_0 + sigma_0 * np.random.randn()
+ for t in range(m):
+ sample_sum += (x - mu_star)**k
+ x = a * x + b + c * np.random.randn()
+ return sample_sum / m
+
+def true_moments_ar1(k):
+ if k % 2 == 0:
+ return std_star**k * factorial2(k - 1)
+ else:
+ return 0
+
+k_vals = np.arange(6) + 1
+sample_moments = np.empty_like(k_vals)
+true_moments = np.empty_like(k_vals)
+
+for k_idx, k in enumerate(k_vals):
+ sample_moments[k_idx] = sample_moments_ar1(k)
+ true_moments[k_idx] = true_moments_ar1(k)
+
+fig, ax = plt.subplots()
+ax.plot(k_vals, true_moments, label="true moments")
+ax.plot(k_vals, sample_moments, label="sample moments")
+ax.legend()
+
+plt.show()
+```
+
+```{solution-end}
+```
+
+
+```{exercise}
+:label: ar1p_ex2
+
+Write your own version of a one dimensional [kernel density
+estimator](https://en.wikipedia.org/wiki/Kernel_density_estimation),
+which estimates a density from a sample.
+
+Write it as a class that takes the data $X$ and bandwidth
+$h$ when initialized and provides a method $f$ such that
+
+$$
+f(x) = \frac{1}{hn} \sum_{i=1}^n
+K \left( \frac{x-X_i}{h} \right)
+$$
+
+For $K$ use the Gaussian kernel ($K$ is the standard normal
+density).
+
+Write the class so that the bandwidth defaults to Silverman’s rule (see
+the “rule of thumb” discussion on [this
+page](https://en.wikipedia.org/wiki/Kernel_density_estimation)). Test
+the class you have written by going through the steps
+
+1. simulate data $X_1, \ldots, X_n$ from distribution $\phi$
+1. plot the kernel density estimate over a suitable range
+1. plot the density of $\phi$ on the same figure
+
+for distributions $\phi$ of the following types
+
+- [beta
+ distribution](https://en.wikipedia.org/wiki/Beta_distribution)
+ with $\alpha = \beta = 2$
+- [beta
+ distribution](https://en.wikipedia.org/wiki/Beta_distribution)
+ with $\alpha = 2$ and $\beta = 5$
+- [beta
+ distribution](https://en.wikipedia.org/wiki/Beta_distribution)
+ with $\alpha = \beta = 0.5$
+
+Use $n=500$.
+
+Make a comment on your results. (Do you think this is a good estimator
+of these distributions?)
+```
+
+
+```{solution-start} ar1p_ex2
+:class: dropdown
+```
+
+Here is one solution:
+
+```{code-cell} ipython3
+K = norm.pdf
+
+class KDE:
+
+ def __init__(self, x_data, h=None):
+
+ if h is None:
+ c = x_data.std()
+ n = len(x_data)
+ h = 1.06 * c * n**(-1/5)
+ self.h = h
+ self.x_data = x_data
+
+ def f(self, x):
+ if np.isscalar(x):
+ return K((x - self.x_data) / self.h).mean() * (1/self.h)
+ else:
+ y = np.empty_like(x)
+ for i, x_val in enumerate(x):
+ y[i] = K((x_val - self.x_data) / self.h).mean() * (1/self.h)
+ return y
+```
+
+```{code-cell} ipython3
+def plot_kde(ϕ, x_min=-0.2, x_max=1.2):
+ x_data = ϕ.rvs(n)
+ kde = KDE(x_data)
+
+ x_grid = np.linspace(-0.2, 1.2, 100)
+ fig, ax = plt.subplots()
+ ax.plot(x_grid, kde.f(x_grid), label="estimate")
+ ax.plot(x_grid, ϕ.pdf(x_grid), label="true density")
+ ax.legend()
+ plt.show()
+```
+
+```{code-cell} ipython3
+from scipy.stats import beta
+
+n = 500
+parameter_pairs= (2, 2), (2, 5), (0.5, 0.5)
+for α, β in parameter_pairs:
+ plot_kde(beta(α, β))
+```
+
+We see that the kernel density estimator is effective when the underlying
+distribution is smooth but less so otherwise.
+
+```{solution-end}
+```
+
+
+```{exercise}
+:label: ar1p_ex3
+
+In the lecture we discussed the following fact: for the $AR(1)$ process
+
+$$
+X_{t+1} = a X_t + b + c W_{t+1}
+$$
+
+with $\{ W_t \}$ iid and standard normal,
+
+$$
+\psi_t = N(\mu, s^2) \implies \psi_{t+1}
+= N(a \mu + b, a^2 s^2 + c^2)
+$$
+
+Confirm this, at least approximately, by simulation. Let
+
+- $a = 0.9$
+- $b = 0.0$
+- $c = 0.1$
+- $\mu = -3$
+- $s = 0.2$
+
+First, plot $\psi_t$ and $\psi_{t+1}$ using the true
+distributions described above.
+
+Second, plot $\psi_{t+1}$ on the same figure (in a different
+color) as follows:
+
+1. Generate $n$ draws of $X_t$ from the $N(\mu, s^2)$
+ distribution
+1. Update them all using the rule
+ $X_{t+1} = a X_t + b + c W_{t+1}$
+1. Use the resulting sample of $X_{t+1}$ values to produce a
+ density estimate via kernel density estimation.
+
+Try this for $n=2000$ and confirm that the
+simulation based estimate of $\psi_{t+1}$ does converge to the
+theoretical distribution.
+```
+
+```{solution-start} ar1p_ex3
+:class: dropdown
+```
+
+Here is our solution
+
+```{code-cell} ipython3
+a = 0.9
+b = 0.0
+c = 0.1
+μ = -3
+s = 0.2
+```
+
+```{code-cell} ipython3
+μ_next = a * μ + b
+s_next = np.sqrt(a**2 * s**2 + c**2)
+```
+
+```{code-cell} ipython3
+ψ = lambda x: K((x - μ) / s)
+ψ_next = lambda x: K((x - μ_next) / s_next)
+```
+
+```{code-cell} ipython3
+ψ = norm(μ, s)
+ψ_next = norm(μ_next, s_next)
+```
+
+```{code-cell} ipython3
+n = 2000
+x_draws = ψ.rvs(n)
+x_draws_next = a * x_draws + b + c * np.random.randn(n)
+kde = KDE(x_draws_next)
+
+x_grid = np.linspace(μ - 1, μ + 1, 100)
+fig, ax = plt.subplots()
+
+ax.plot(x_grid, ψ.pdf(x_grid), label="$\psi_t$")
+ax.plot(x_grid, ψ_next.pdf(x_grid), label="$\psi_{t+1}$")
+ax.plot(x_grid, kde.f(x_grid), label="estimate of $\psi_{t+1}$")
+
+ax.legend()
+plt.show()
+```
+
+The simulated distribution approximately coincides with the theoretical
+distribution, as predicted.
+
+```{solution-end}
+```
diff --git a/content/lectures/business_cycle.ipynb b/book/_build/html/_sources/business_cycle.ipynb
similarity index 77%
rename from content/lectures/business_cycle.ipynb
rename to book/_build/html/_sources/business_cycle.ipynb
index c82eb38..1b6e1f8 100644
--- a/content/lectures/business_cycle.ipynb
+++ b/book/_build/html/_sources/business_cycle.ipynb
@@ -2,31 +2,28 @@
"cells": [
{
"cell_type": "markdown",
- "id": "11b8ef2e",
- "metadata": {
- "user_expressions": []
- },
+ "id": "caf98cc7",
+ "metadata": {},
"source": [
"# Business Cycles\n",
"\n",
"## Overview\n",
"\n",
- "In this lecture we study business cycles\n",
+ "In this lecture we review some empirical aspects of business cycles.\n",
"\n",
"Business cycles are fluctuations in economic activity over time.\n",
"\n",
- "These fluctuations are in the form of expansions (booms), contractions (recessions), and recoveries.\n",
+ "These include expansions (also called booms) and contractions (also called recessions).\n",
"\n",
- "We will look into a series of economic indicators to visualize the expansions and contractions of economies using [World Bank](https://documents.worldbank.org/en/publication/documents-reports/api) and [FRED](https://fred.stlouisfed.org/) data.\n",
+ "For our study, we will use economic indicators from the [World Bank](https://documents.worldbank.org/en/publication/documents-reports/api) and [FRED](https://fred.stlouisfed.org/).\n",
"\n",
- "In addition to those installed by Anaconda, this lecture requires\n",
- "libraries to obtain World Bank and FRED data:"
+ "In addition to the packages already installed by Anaconda, this lecture requires"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "97df2b46",
+ "id": "00e4a748",
"metadata": {
"tags": [
"hide-output"
@@ -40,7 +37,7 @@
},
{
"cell_type": "markdown",
- "id": "c0529c90",
+ "id": "87b4f82a",
"metadata": {},
"source": [
"We use the following imports"
@@ -49,23 +46,29 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "d30d82c8",
+ "id": "914537c0",
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import pandas as pd\n",
- "import numpy as np\n",
- "import scipy.stats as st\n",
"import datetime\n",
"import wbgapi as wb\n",
"import pandas_datareader.data as web"
]
},
+ {
+ "cell_type": "markdown",
+ "id": "b45301f9",
+ "metadata": {},
+ "source": [
+ "Here's some minor code to help with colors in our plots."
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
- "id": "92c80cad",
+ "id": "d0c634bd",
"metadata": {
"tags": [
"hide-input"
@@ -73,7 +76,7 @@
},
"outputs": [],
"source": [
- "# Set Graphical Parameters\n",
+ "# Set graphical parameters\n",
"cycler = plt.cycler(linestyle=['-', '-.', '--', ':'], \n",
" color=['#377eb8', '#ff7f00', '#4daf4a', '#ff334f'])\n",
"plt.rc('axes', prop_cycle=cycler)"
@@ -81,28 +84,23 @@
},
{
"cell_type": "markdown",
- "id": "cec6e879",
- "metadata": {
- "user_expressions": []
- },
+ "id": "5fc2d1ff",
+ "metadata": {},
"source": [
"## Data acquisition\n",
"\n",
- "We will use `wbgapi` and `pandas_datareader` to retrieve data throughout this\n",
- "lecture.\n",
- "\n",
- "Let's explore how to query data first.\n",
+ "We will use the World Bank's data API `wbgapi` and `pandas_datareader` to retrieve data.\n",
"\n",
"We can use `wb.series.info` with the argument `q` to query available data from\n",
"the [World Bank](https://www.worldbank.org/en/home).\n",
"\n",
- "For example, let's retrieve the ID to query GDP growth data."
+ "For example, let's retrieve the GDP growth data ID to query GDP growth data."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "0685f5f4",
+ "id": "ab47b32f",
"metadata": {},
"outputs": [],
"source": [
@@ -111,10 +109,8 @@
},
{
"cell_type": "markdown",
- "id": "3e4ba1dc",
- "metadata": {
- "user_expressions": []
- },
+ "id": "23ebd2c9",
+ "metadata": {},
"source": [
"Now we use this series ID to obtain the data."
]
@@ -122,12 +118,8 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "2eeb9846",
- "metadata": {
- "tags": [
- "hide-output"
- ]
- },
+ "id": "e04a685b",
+ "metadata": {},
"outputs": [],
"source": [
"gdp_growth = wb.data.DataFrame('NY.GDP.MKTP.KD.ZG',\n",
@@ -138,18 +130,16 @@
},
{
"cell_type": "markdown",
- "id": "2b9c80b6",
- "metadata": {
- "user_expressions": []
- },
+ "id": "c91aff26",
+ "metadata": {},
"source": [
- "We can the metadata to learn more about the series."
+ "We can look at the series' metadata to learn more about the series (click to expand)."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "e45f314c",
+ "id": "89771623",
"metadata": {
"tags": [
"hide-output"
@@ -162,17 +152,13 @@
},
{
"cell_type": "markdown",
- "id": "999d432d",
- "metadata": {
- "user_expressions": []
- },
+ "id": "1febc7f1",
+ "metadata": {},
"source": [
- "Let's dive into the data with the tools we have.\n",
- "\n",
"(gdp_growth)=\n",
"## GDP growth rate\n",
"\n",
- "First we look at the GDP growth rate. \n",
+ "First we look at GDP growth. \n",
"\n",
"Let's source our data from the World Bank and clean it."
]
@@ -180,11 +166,11 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "10fc11b3",
+ "id": "73518684",
"metadata": {},
"outputs": [],
"source": [
- "# Use the series ID retrived before\n",
+ "# Use the series ID retrieved before\n",
"gdp_growth = wb.data.DataFrame('NY.GDP.MKTP.KD.ZG',\n",
" ['USA', 'ARG', 'GBR', 'GRC', 'JPN'], \n",
" labels=True)\n",
@@ -194,7 +180,7 @@
},
{
"cell_type": "markdown",
- "id": "9f3fc314",
+ "id": "9e8c31b2",
"metadata": {},
"source": [
"Here's a first look at the data"
@@ -203,7 +189,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "b689e1c1",
+ "id": "2ea9091c",
"metadata": {},
"outputs": [],
"source": [
@@ -212,16 +198,16 @@
},
{
"cell_type": "markdown",
- "id": "5f34aace",
+ "id": "f3b8c8a1",
"metadata": {},
"source": [
- "Now we can write a function to generate plots for individual countries taking into account the recessions."
+ "We write a function to generate plots for individual countries taking into account the recessions."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "4bfe95ee",
+ "id": "f63709bd",
"metadata": {
"tags": [
"hide-input"
@@ -266,7 +252,7 @@
"\n",
" ax.plot(data.loc[country], label=country, **g_params)\n",
" \n",
- " # Highlight Recessions\n",
+ " # Highlight recessions\n",
" ax.axvspan(1973, 1975, **b_params)\n",
" ax.axvspan(1990, 1992, **b_params)\n",
" ax.axvspan(2007, 2009, **b_params)\n",
@@ -302,20 +288,16 @@
},
{
"cell_type": "markdown",
- "id": "16b26069",
- "metadata": {
- "user_expressions": []
- },
+ "id": "513aa2a0",
+ "metadata": {},
"source": [
- "Now we can plot the data as a time series.\n",
- "\n",
"Let's start with the United States."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "4b689bee",
+ "id": "8c7cba82",
"metadata": {
"mystnb": {
"figure": {
@@ -338,7 +320,7 @@
},
{
"cell_type": "markdown",
- "id": "9893f9cc",
+ "id": "9c43750a",
"metadata": {
"user_expressions": []
},
@@ -352,7 +334,7 @@
},
{
"cell_type": "markdown",
- "id": "3b0154a3",
+ "id": "29de286d",
"metadata": {},
"source": [
"The United Kingdom (UK) has a similar pattern to the US, with a slow decline\n",
@@ -364,7 +346,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "f543e2ee",
+ "id": "a3be0141",
"metadata": {
"mystnb": {
"figure": {
@@ -386,7 +368,7 @@
},
{
"cell_type": "markdown",
- "id": "bd115d5f",
+ "id": "a7e7a83f",
"metadata": {
"user_expressions": []
},
@@ -395,13 +377,13 @@
"1970s, followed by slowed expansion in the past two decades.\n",
"\n",
"Major dips in the growth rate coincided with the Oil Crisis of the 1970s, the\n",
- "GFC and the Covid-19 pandemic."
+ "Global Financial Crisis (GFC) and the Covid-19 pandemic."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "1f7e9b88",
+ "id": "0b3b1e65",
"metadata": {
"mystnb": {
"figure": {
@@ -423,7 +405,7 @@
},
{
"cell_type": "markdown",
- "id": "d4f24268",
+ "id": "f36b97eb",
"metadata": {},
"source": [
"Now let's study Greece."
@@ -432,7 +414,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "10ef6b82",
+ "id": "5ffc23f7",
"metadata": {
"mystnb": {
"figure": {
@@ -454,10 +436,10 @@
},
{
"cell_type": "markdown",
- "id": "53324961",
+ "id": "1ad571b8",
"metadata": {},
"source": [
- "Greece had a significant drop in GDP growth around 2010-2011, during the peak\n",
+ "Greece experienced a very large drop in GDP growth around 2010-2011, during the peak\n",
"of the Greek debt crisis.\n",
"\n",
"Next let's consider Argentina."
@@ -466,7 +448,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "dc6f53e6",
+ "id": "f29c8960",
"metadata": {
"mystnb": {
"figure": {
@@ -488,39 +470,27 @@
},
{
"cell_type": "markdown",
- "id": "7cad6b79",
- "metadata": {
- "user_expressions": []
- },
+ "id": "5fe617e0",
+ "metadata": {},
"source": [
- "The figure shows that Argentina has experienced more volatile cycles than\n",
- "the economies mentioned above.\n",
+ "Notice that Argentina has experienced far more volatile cycles than\n",
+ "the economies examined above.\n",
+ "\n",
+ "At the same time, Argentina's growth rate did not fall during the two developed\n",
+ "economy recessions in the 1970s and 1990s.\n",
+ "\n",
"\n",
- "At the same time, growth of Argentina did not fall during the two developed\n",
- "economy recessions in the 1970s and 1990s."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "f819f097",
- "metadata": {
- "user_expressions": []
- },
- "source": [
"## Unemployment\n",
"\n",
"Another important measure of business cycles is the unemployment rate.\n",
"\n",
- "During a recession, it is more likely that a larger proportion of the working\n",
- "population will be laid off.\n",
- "\n",
- "We demonstrate this using a long-run unemployment rate from FRED spanning from [1929-1942](https://fred.stlouisfed.org/series/M0892AUSM156SNBR) to [1948-2022](https://fred.stlouisfed.org/series/UNRATE) with the unemployment rate between 1942 and 1948 estimated by the [Census Bureau](https://www.census.gov/library/publications/1975/compendia/hist_stats_colonial-1970.html)."
+ "We study unemployment using rate data from FRED spanning from [1929-1942](https://fred.stlouisfed.org/series/M0892AUSM156SNBR) to [1948-2022](https://fred.stlouisfed.org/series/UNRATE), combined unemployment rate data over 1942-1948 estimated by the [Census Bureau](https://www.census.gov/library/publications/1975/compendia/hist_stats_colonial-1970.html)."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "48ca10a1",
+ "id": "52af17f7",
"metadata": {
"tags": [
"hide-input"
@@ -545,16 +515,17 @@
},
{
"cell_type": "markdown",
- "id": "59434cf3",
+ "id": "18a29b40",
"metadata": {},
"source": [
- "Now we plot the long-run unemployment rate in the US from 1929 to 2022 with recession defined by NBER"
+ "Let's plot the unemployment rate in the US from 1929 to 2022 with recessions\n",
+ "defined by the NBER."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "00dd2ab1",
+ "id": "b85a210f",
"metadata": {
"mystnb": {
"figure": {
@@ -612,52 +583,40 @@
},
{
"cell_type": "markdown",
- "id": "ad3c06d5",
- "metadata": {
- "user_expressions": []
- },
+ "id": "a2eb1642",
+ "metadata": {},
"source": [
- "In the plot, we can see that the expansions and contractions of the labor\n",
- "market have been highly correlated with recessions. \n",
- "\n",
- "However, there is often a delay in the recovery of the labor market after\n",
- "recessions.\n",
+ "The plot shows that \n",
"\n",
- "This trend is clearly visible in the 1930s, as well as in recessions in the\n",
- "1980s. \n",
+ "* expansions and contractions of the labor market have been highly correlated\n",
+ " with recessions. \n",
+ "* cycles are, in general, asymmetric: sharp rises in unemployment are followed\n",
+ " by slow recoveries.\n",
"\n",
- "It also shows us how unique labor market conditions have been during the\n",
+ "It also shows us how unique labor market conditions were in the US during the\n",
"post-pandemic recovery. \n",
"\n",
- "The labor market has recovered at an unprecedented rate, leading to the\n",
- "tightest point in the past decades after the shock in 2020-2021."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "a7408189",
- "metadata": {
- "user_expressions": []
- },
- "source": [
+ "The labor market recovered at an unprecedented rate after the shock in 2020-2021.\n",
+ "\n",
+ "\n",
"(synchronization)=\n",
"## Synchronization\n",
"\n",
"In our {ref}`previous discussion`, we found that developed economies have had\n",
"relatively synchronized periods of recession. \n",
"\n",
- "At the same time, this synchronization does not appear in Argentina until the 2000s. \n",
+ "At the same time, this synchronization did not appear in Argentina until the 2000s. \n",
"\n",
"Let's examine this trend further. \n",
"\n",
"With slight modifications, we can use our previous function to draw a plot\n",
- "that includes many countries"
+ "that includes multiple countries."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "5d0c832f",
+ "id": "e59fe92c",
"metadata": {
"tags": [
"hide-input"
@@ -706,7 +665,7 @@
" for country in countries:\n",
" ax.plot(data.loc[country], label=country, **g_params)\n",
" \n",
- " # Highlight Recessions\n",
+ " # Highlight recessions\n",
" ax.axvspan(1973, 1975, **b_params)\n",
" ax.axvspan(1990, 1992, **b_params)\n",
" ax.axvspan(2007, 2009, **b_params)\n",
@@ -739,7 +698,7 @@
},
{
"cell_type": "markdown",
- "id": "9e6dfa7a",
+ "id": "6fbe4b76",
"metadata": {},
"source": [
"Here we compare the GDP growth rate of developed economies and developing economies."
@@ -748,7 +707,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "5958d778",
+ "id": "5d0c82c9",
"metadata": {
"tags": [
"hide-input"
@@ -766,16 +725,16 @@
},
{
"cell_type": "markdown",
- "id": "0362e477",
+ "id": "e2fb4854",
"metadata": {},
"source": [
- "We use the United Kingdom, United States, Germany, and Japan as examples of developed economies"
+ "We use the United Kingdom, United States, Germany, and Japan as examples of developed economies."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "8e0ffe1a",
+ "id": "96f20aa9",
"metadata": {
"mystnb": {
"figure": {
@@ -801,16 +760,16 @@
},
{
"cell_type": "markdown",
- "id": "cf3f9ca5",
+ "id": "bab2ea48",
"metadata": {},
"source": [
- "We choose Brazil, China, Argentina, and Mexico as representative developing economies"
+ "We choose Brazil, China, Argentina, and Mexico as representative developing economies."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "69915fec",
+ "id": "ee361485",
"metadata": {
"mystnb": {
"figure": {
@@ -835,31 +794,29 @@
},
{
"cell_type": "markdown",
- "id": "32ce06aa",
- "metadata": {
- "user_expressions": []
- },
+ "id": "bf1df65d",
+ "metadata": {},
"source": [
- "The comparison of GDP growth rates above shows that \n",
+ "The comparison of GDP growth rates above suggests that \n",
"business cycles are becoming more synchronized in 21st-century recessions.\n",
"\n",
"However, emerging and less developed economies often experience more volatile\n",
"changes throughout the economic cycles. \n",
"\n",
- "Despite of the synchronization in GDP growth, the experience of individual countries during\n",
+ "Despite the synchronization in GDP growth, the experience of individual countries during\n",
"the recession often differs. \n",
"\n",
- "We use unemployment rate and the recovery of labor market conditions\n",
+ "We use the unemployment rate and the recovery of labor market conditions\n",
"as another example.\n",
"\n",
"Here we compare the unemployment rate of the United States, \n",
- "United Kingdom, Japan, and France"
+ "the United Kingdom, Japan, and France."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "9f04da26",
+ "id": "d6c39f02",
"metadata": {
"mystnb": {
"figure": {
@@ -890,24 +847,16 @@
},
{
"cell_type": "markdown",
- "id": "732fcf4f",
+ "id": "5b2f65f1",
"metadata": {},
"source": [
- "France, with its strong labor unions, has a prolonged labor market recovery\n",
- "compared to the US and UK. \n",
+ "We see that France, with its strong labor unions, typically experiences\n",
+ "relatively slow labor market recoveries after negative shocks.\n",
+ "\n",
+ "We also notice that Japan has a history of very low and stable unemployment rates.\n",
"\n",
- "However, Japan has a history of very low and stable unemployment rates due to\n",
- "a constellation of social, demographic, and cultural factors."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "b2f76eec",
- "metadata": {
- "user_expressions": []
- },
- "source": [
- "## Leading indicators and correlated factors for business cycles\n",
+ "\n",
+ "## Leading indicators and correlated factors \n",
"\n",
"Examining leading indicators and correlated factors helps policymakers to\n",
"understand the causes and results of business cycles. \n",
@@ -915,38 +864,25 @@
"We will discuss potential leading indicators and correlated factors from three\n",
"perspectives: consumption, production, and credit level.\n",
"\n",
- "### Consumption"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "0596c926",
- "metadata": {
- "user_expressions": []
- },
- "source": [
+ "\n",
+ "### Consumption\n",
+ "\n",
"Consumption depends on consumers' confidence towards their\n",
"income and the overall performance of the economy in the future. \n",
"\n",
"One widely cited indicator for consumer confidence is the [consumer sentiment index](https://fred.stlouisfed.org/series/UMCSENT) published by the University\n",
"of Michigan.\n",
"\n",
- "Consumer sentiment remains high during during expansion, but there are significant drops before recession hits.\n",
- "\n",
- "There is also a clear negative correlation between consumer sentiment and [core consumer price index](https://fred.stlouisfed.org/series/CPILFESL).\n",
- "\n",
- "This trend is more significant in the during [stagflation](https://en.wikipedia.org/wiki/Stagflation).\n",
- "\n",
- "When the price of consumer commodities rises, consumer confidence diminishes.\n",
- "\n",
- "We plot the University of Michigan Consumer Sentiment Index and\n",
- "Year-over-year Consumer Price Index Change from 1978-2022 in the US to show this trend"
+ "Here we plot the University of Michigan Consumer Sentiment Index and\n",
+ "year-on-year \n",
+ "[core consumer price index](https://fred.stlouisfed.org/series/CPILFESL)\n",
+ "(CPI) change from 1978-2022 in the US."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "ce2b6221",
+ "id": "e7b31adf",
"metadata": {
"mystnb": {
"figure": {
@@ -1013,35 +949,40 @@
},
{
"cell_type": "markdown",
- "id": "712c4f74",
- "metadata": {
- "user_expressions": []
- },
+ "id": "7106ce20",
+ "metadata": {},
"source": [
- "### Production\n",
+ "We see that \n",
"\n",
- "Consumers' confidence often influences their consumption pattern.\n",
+ "* consumer sentiment often remains high during expansions and\n",
+ "drops before recessions.\n",
+ "* there is a clear negative correlation between consumer sentiment and the CPI.\n",
+ "\n",
+ "When the price of consumer commodities rises, consumer confidence diminishes.\n",
"\n",
- "This often manifests on the production side.\n",
+ "This trend is more significant during [stagflation](https://en.wikipedia.org/wiki/Stagflation).\n",
+ "\n",
+ "\n",
+ "\n",
+ "### Production\n",
"\n",
- "The real industrial output is highly correlated with\n",
- "recessions in the economy. \n",
+ "Real industrial output is highly correlated with recessions in the economy. \n",
"\n",
"However, it is not a leading indicator, as the peak of contraction in production \n",
- "delays compared to consumer confidence and inflation.\n",
+ "is delayed relative to consumer confidence and inflation.\n",
"\n",
"We plot the real industrial output change from the previous year \n",
- "from 1919 to 2022 in the US to show this trend"
+ "from 1919 to 2022 in the US to show this trend."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "10c7ee74",
+ "id": "b7c2ad3f",
"metadata": {
"mystnb": {
"figure": {
- "caption": "YoY real ouput change, US (%)",
+ "caption": "YoY real output change, US (%)",
"name": "roc"
}
},
@@ -1056,13 +997,13 @@
"\n",
"nber = web.DataReader('USREC', 'fred', \n",
" start_date, end_date)\n",
- "consumer_confidence = web.DataReader('INDPRO', 'fred', \n",
+ "industrial_output = web.DataReader('INDPRO', 'fred', \n",
" start_date, end_date).pct_change(12)*100\n",
"\n",
"fig, ax = plt.subplots()\n",
- "ax.plot(consumer_confidence, **g_params, \n",
+ "ax.plot(industrial_output, **g_params, \n",
" color='#377eb8', linestyle='-', \n",
- " linewidth=2, label='Consumer price index')\n",
+ " linewidth=2, label='Industrial production index')\n",
"ax.fill_between(nber.index, 0, 1,\n",
" where=nber['USREC']==1, \n",
" color='grey', edgecolor='none',\n",
@@ -1070,43 +1011,36 @@
" transform=ax.get_xaxis_transform(), \n",
" label='NBER recession indicators')\n",
"ax.set_ylim([ax.get_ylim()[0], ax.get_ylim()[1]])\n",
- "ax.set_ylabel('YoY real ouput change (%)')\n",
+ "ax.set_ylabel('YoY real output change (%)')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
- "id": "f57196ce",
+ "id": "26cc287c",
"metadata": {},
"source": [
- "We observe the delayed contraction in the plot across recessions."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "83813a5e",
- "metadata": {
- "user_expressions": []
- },
- "source": [
+ "We observe the delayed contraction in the plot across recessions.\n",
+ "\n",
+ "\n",
"### Credit level\n",
"\n",
"Credit contractions often occur during recessions, as lenders become more\n",
"cautious and borrowers become more hesitant to take on additional debt.\n",
"\n",
- "This can be due to several factors such as a decrease in overall economic\n",
- "activity, rising unemployment, and gloomy expectations for the future.\n",
+ "This is due to factors such as a decrease in overall economic\n",
+ "activity and gloomy expectations for the future.\n",
"\n",
"One example is domestic credit to the private sector by banks in the UK.\n",
"\n",
- "The following graph shows the domestic credit to the private sector \n",
- "as a percentage of GDP by banks from 1970 to 2022 in the UK"
+ "The following graph shows the domestic credit to the private sector as a\n",
+ "percentage of GDP by banks from 1970 to 2022 in the UK."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "d88e4cf5",
+ "id": "b10dfac2",
"metadata": {
"mystnb": {
"figure": {
@@ -1137,31 +1071,81 @@
},
{
"cell_type": "markdown",
- "id": "0c430dea",
- "metadata": {
- "user_expressions": []
- },
+ "id": "45287194",
+ "metadata": {},
"source": [
- "Note that the credit rises during economic expansion\n",
+ "Note that the credit rises during economic expansions\n",
"and stagnates or even contracts after recessions."
]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "f678b37e",
- "metadata": {},
- "outputs": [],
- "source": []
}
],
"metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.14.5"
+ }
+ },
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
- }
+ },
+ "source_map": [
+ 12,
+ 28,
+ 33,
+ 37,
+ 43,
+ 47,
+ 54,
+ 66,
+ 68,
+ 73,
+ 78,
+ 83,
+ 87,
+ 98,
+ 105,
+ 109,
+ 111,
+ 115,
+ 187,
+ 192,
+ 210,
+ 218,
+ 225,
+ 242,
+ 250,
+ 265,
+ 269,
+ 284,
+ 291,
+ 306,
+ 321,
+ 337,
+ 342,
+ 391,
+ 420,
+ 495,
+ 499,
+ 511,
+ 515,
+ 532,
+ 536,
+ 552,
+ 570,
+ 592,
+ 622,
+ 680,
+ 704,
+ 734,
+ 752,
+ 774
+ ]
},
"nbformat": 4,
"nbformat_minor": 5
-}
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/business_cycle.md b/book/_build/html/_sources/business_cycle.md
new file mode 100644
index 0000000..b2ed848
--- /dev/null
+++ b/book/_build/html/_sources/business_cycle.md
@@ -0,0 +1,777 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.14.5
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+# Business Cycles
+
+## Overview
+
+In this lecture we review some empirical aspects of business cycles.
+
+Business cycles are fluctuations in economic activity over time.
+
+These include expansions (also called booms) and contractions (also called recessions).
+
+For our study, we will use economic indicators from the [World Bank](https://documents.worldbank.org/en/publication/documents-reports/api) and [FRED](https://fred.stlouisfed.org/).
+
+In addition to the packages already installed by Anaconda, this lecture requires
+
+```{code-cell} ipython3
+:tags: [hide-output]
+
+%pip install wbgapi
+%pip install pandas-datareader
+```
+
+We use the following imports
+
+```{code-cell} ipython3
+import matplotlib.pyplot as plt
+import pandas as pd
+import datetime
+import wbgapi as wb
+import pandas_datareader.data as web
+```
+
+Here's some minor code to help with colors in our plots.
+
+```{code-cell} ipython3
+:tags: [hide-input]
+
+# Set graphical parameters
+cycler = plt.cycler(linestyle=['-', '-.', '--', ':'],
+ color=['#377eb8', '#ff7f00', '#4daf4a', '#ff334f'])
+plt.rc('axes', prop_cycle=cycler)
+```
+
+
+## Data acquisition
+
+We will use the World Bank's data API `wbgapi` and `pandas_datareader` to retrieve data.
+
+We can use `wb.series.info` with the argument `q` to query available data from
+the [World Bank](https://www.worldbank.org/en/home).
+
+For example, let's retrieve the GDP growth data ID to query GDP growth data.
+
+```{code-cell} ipython3
+wb.series.info(q='GDP growth')
+```
+
+
+Now we use this series ID to obtain the data.
+
+```{code-cell} ipython3
+gdp_growth = wb.data.DataFrame('NY.GDP.MKTP.KD.ZG',
+ ['USA', 'ARG', 'GBR', 'GRC', 'JPN'],
+ labels=True)
+gdp_growth
+```
+
+
+We can look at the series' metadata to learn more about the series (click to expand).
+
+```{code-cell} ipython3
+:tags: [hide-output]
+
+wb.series.metadata.get('NY.GDP.MKTP.KD.ZG')
+```
+
+
+
+(gdp_growth)=
+## GDP growth rate
+
+First we look at GDP growth.
+
+Let's source our data from the World Bank and clean it.
+
+```{code-cell} ipython3
+# Use the series ID retrieved before
+gdp_growth = wb.data.DataFrame('NY.GDP.MKTP.KD.ZG',
+ ['USA', 'ARG', 'GBR', 'GRC', 'JPN'],
+ labels=True)
+gdp_growth = gdp_growth.set_index('Country')
+gdp_growth.columns = gdp_growth.columns.str.replace('YR', '').astype(int)
+```
+
+Here's a first look at the data
+
+```{code-cell} ipython3
+gdp_growth
+```
+
+We write a function to generate plots for individual countries taking into account the recessions.
+
+```{code-cell} ipython3
+:tags: [hide-input]
+
+def plot_series(data, country, ylabel,
+ txt_pos, ax, g_params,
+ b_params, t_params, ylim=15, baseline=0):
+ """
+ Plots a time series with recessions highlighted.
+
+ Parameters
+ ----------
+ data : pd.DataFrame
+ Data to plot
+ country : str
+ Name of the country to plot
+ ylabel : str
+ Label of the y-axis
+ txt_pos : float
+ Position of the recession labels
+ y_lim : float
+ Limit of the y-axis
+ ax : matplotlib.axes._subplots.AxesSubplot
+ Axes to plot on
+ g_params : dict
+ Parameters for the line
+ b_params : dict
+ Parameters for the recession highlights
+ t_params : dict
+ Parameters for the recession labels
+ baseline : float, optional
+ Dashed baseline on the plot, by default 0
+
+ Returns
+ -------
+ ax : matplotlib.axes.Axes
+ Axes with the plot.
+ """
+
+ ax.plot(data.loc[country], label=country, **g_params)
+
+ # Highlight recessions
+ ax.axvspan(1973, 1975, **b_params)
+ ax.axvspan(1990, 1992, **b_params)
+ ax.axvspan(2007, 2009, **b_params)
+ ax.axvspan(2019, 2021, **b_params)
+ if ylim != None:
+ ax.set_ylim([-ylim, ylim])
+ else:
+ ylim = ax.get_ylim()[1]
+ ax.text(1974, ylim + ylim*txt_pos,
+ 'Oil Crisis\n(1974)', **t_params)
+ ax.text(1991, ylim + ylim*txt_pos,
+ '1990s recession\n(1991)', **t_params)
+ ax.text(2008, ylim + ylim*txt_pos,
+ 'GFC\n(2008)', **t_params)
+ ax.text(2020, ylim + ylim*txt_pos,
+ 'Covid-19\n(2020)', **t_params)
+
+ # Add a baseline for reference
+ if baseline != None:
+ ax.axhline(y=baseline,
+ color='black',
+ linestyle='--')
+ ax.set_ylabel(ylabel)
+ ax.legend()
+ return ax
+
+# Define graphical parameters
+g_params = {'alpha': 0.7}
+b_params = {'color':'grey', 'alpha': 0.2}
+t_params = {'color':'grey', 'fontsize': 9,
+ 'va':'center', 'ha':'center'}
+```
+
+
+Let's start with the United States.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "United States (GDP growth rate %)"
+ name: us_gdp
+---
+
+fig, ax = plt.subplots()
+
+country = 'United States'
+ylabel = 'GDP growth rate (%)'
+plot_series(gdp_growth, country,
+ ylabel, 0.1, ax,
+ g_params, b_params, t_params)
+plt.show()
+```
+
++++ {"user_expressions": []}
+
+GDP growth is positive on average and trending slightly downward over time.
+
+We also see fluctuations over GDP growth over time, some of which are quite large.
+
+Let's look at a few more countries to get a basis for comparison.
+
++++
+
+The United Kingdom (UK) has a similar pattern to the US, with a slow decline
+in the growth rate and significant fluctuations.
+
+Notice the very large dip during the Covid-19 pandemic.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "United Kingdom (GDP growth rate %)"
+ name: uk_gdp
+---
+
+fig, ax = plt.subplots()
+
+country = 'United Kingdom'
+plot_series(gdp_growth, country,
+ ylabel, 0.1, ax,
+ g_params, b_params, t_params)
+plt.show()
+```
+
++++ {"user_expressions": []}
+
+Now let's consider Japan, which experienced rapid growth in the 1960s and
+1970s, followed by slowed expansion in the past two decades.
+
+Major dips in the growth rate coincided with the Oil Crisis of the 1970s, the
+Global Financial Crisis (GFC) and the Covid-19 pandemic.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Japan (GDP growth rate %)"
+ name: jp_gdp
+---
+
+fig, ax = plt.subplots()
+
+country = 'Japan'
+plot_series(gdp_growth, country,
+ ylabel, 0.1, ax,
+ g_params, b_params, t_params)
+plt.show()
+```
+
+Now let's study Greece.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Greece (GDP growth rate %)"
+ name: gc_gdp
+---
+
+fig, ax = plt.subplots()
+
+country = 'Greece'
+plot_series(gdp_growth, country,
+ ylabel, 0.1, ax,
+ g_params, b_params, t_params)
+plt.show()
+```
+
+Greece experienced a very large drop in GDP growth around 2010-2011, during the peak
+of the Greek debt crisis.
+
+Next let's consider Argentina.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Argentina (GDP growth rate %)"
+ name: arg_gdp
+---
+
+fig, ax = plt.subplots()
+
+country = 'Argentina'
+plot_series(gdp_growth, country,
+ ylabel, 0.1, ax,
+ g_params, b_params, t_params)
+plt.show()
+```
+
+Notice that Argentina has experienced far more volatile cycles than
+the economies examined above.
+
+At the same time, Argentina's growth rate did not fall during the two developed
+economy recessions in the 1970s and 1990s.
+
+
+## Unemployment
+
+Another important measure of business cycles is the unemployment rate.
+
+We study unemployment using rate data from FRED spanning from [1929-1942](https://fred.stlouisfed.org/series/M0892AUSM156SNBR) to [1948-2022](https://fred.stlouisfed.org/series/UNRATE), combined unemployment rate data over 1942-1948 estimated by the [Census Bureau](https://www.census.gov/library/publications/1975/compendia/hist_stats_colonial-1970.html).
+
+```{code-cell} ipython3
+:tags: [hide-input]
+
+start_date = datetime.datetime(1929, 1, 1)
+end_date = datetime.datetime(1942, 6, 1)
+
+unrate_history = web.DataReader('M0892AUSM156SNBR',
+ 'fred', start_date,end_date)
+unrate_history.rename(columns={'M0892AUSM156SNBR': 'UNRATE'},
+ inplace=True)
+
+start_date = datetime.datetime(1948, 1, 1)
+end_date = datetime.datetime(2022, 12, 31)
+
+unrate = web.DataReader('UNRATE', 'fred',
+ start_date, end_date)
+```
+
+Let's plot the unemployment rate in the US from 1929 to 2022 with recessions
+defined by the NBER.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Long-run unemployment rate, US (%)"
+ name: lrunrate
+tags: [hide-input]
+---
+
+# We use the census bureau's estimate for the unemployment rate
+# between 1942 and 1948
+years = [datetime.datetime(year, 6, 1) for year in range(1942, 1948)]
+unrate_census = [4.7, 1.9, 1.2, 1.9, 3.9, 3.9]
+
+unrate_census = {'DATE': years, 'UNRATE': unrate_census}
+unrate_census = pd.DataFrame(unrate_census)
+unrate_census.set_index('DATE', inplace=True)
+
+# Obtain the NBER-defined recession periods
+start_date = datetime.datetime(1929, 1, 1)
+end_date = datetime.datetime(2022, 12, 31)
+
+nber = web.DataReader('USREC', 'fred', start_date, end_date)
+
+fig, ax = plt.subplots()
+
+ax.plot(unrate_history, **g_params,
+ color='#377eb8',
+ linestyle='-', linewidth=2)
+ax.plot(unrate_census, **g_params,
+ color='black', linestyle='--',
+ label='Census estimates', linewidth=2)
+ax.plot(unrate, **g_params, color='#377eb8',
+ linestyle='-', linewidth=2)
+
+# Draw gray boxes according to NBER recession indicators
+ax.fill_between(nber.index, 0, 1,
+ where=nber['USREC']==1,
+ color='grey', edgecolor='none',
+ alpha=0.3,
+ transform=ax.get_xaxis_transform(),
+ label='NBER recession indicators')
+ax.set_ylim([0, ax.get_ylim()[1]])
+ax.legend(loc='upper center',
+ bbox_to_anchor=(0.5, 1.1),
+ ncol=3, fancybox=True, shadow=True)
+ax.set_ylabel('unemployment rate (%)')
+
+plt.show()
+```
+
+
+The plot shows that
+
+* expansions and contractions of the labor market have been highly correlated
+ with recessions.
+* cycles are, in general, asymmetric: sharp rises in unemployment are followed
+ by slow recoveries.
+
+It also shows us how unique labor market conditions were in the US during the
+post-pandemic recovery.
+
+The labor market recovered at an unprecedented rate after the shock in 2020-2021.
+
+
+(synchronization)=
+## Synchronization
+
+In our {ref}`previous discussion`, we found that developed economies have had
+relatively synchronized periods of recession.
+
+At the same time, this synchronization did not appear in Argentina until the 2000s.
+
+Let's examine this trend further.
+
+With slight modifications, we can use our previous function to draw a plot
+that includes multiple countries.
+
+```{code-cell} ipython3
+---
+tags: [hide-input]
+---
+
+
+def plot_comparison(data, countries,
+ ylabel, txt_pos, y_lim, ax,
+ g_params, b_params, t_params,
+ baseline=0):
+ """
+ Plot multiple series on the same graph
+
+ Parameters
+ ----------
+ data : pd.DataFrame
+ Data to plot
+ countries : list
+ List of countries to plot
+ ylabel : str
+ Label of the y-axis
+ txt_pos : float
+ Position of the recession labels
+ y_lim : float
+ Limit of the y-axis
+ ax : matplotlib.axes._subplots.AxesSubplot
+ Axes to plot on
+ g_params : dict
+ Parameters for the lines
+ b_params : dict
+ Parameters for the recession highlights
+ t_params : dict
+ Parameters for the recession labels
+ baseline : float, optional
+ Dashed baseline on the plot, by default 0
+
+ Returns
+ -------
+ ax : matplotlib.axes.Axes
+ Axes with the plot.
+ """
+
+ # Allow the function to go through more than one series
+ for country in countries:
+ ax.plot(data.loc[country], label=country, **g_params)
+
+ # Highlight recessions
+ ax.axvspan(1973, 1975, **b_params)
+ ax.axvspan(1990, 1992, **b_params)
+ ax.axvspan(2007, 2009, **b_params)
+ ax.axvspan(2019, 2021, **b_params)
+ if y_lim != None:
+ ax.set_ylim([-y_lim, y_lim])
+ ylim = ax.get_ylim()[1]
+ ax.text(1974, ylim + ylim*txt_pos,
+ 'Oil Crisis\n(1974)', **t_params)
+ ax.text(1991, ylim + ylim*txt_pos,
+ '1990s recession\n(1991)', **t_params)
+ ax.text(2008, ylim + ylim*txt_pos,
+ 'GFC\n(2008)', **t_params)
+ ax.text(2020, ylim + ylim*txt_pos,
+ 'Covid-19\n(2020)', **t_params)
+ if baseline != None:
+ ax.hlines(y=baseline, xmin=ax.get_xlim()[0],
+ xmax=ax.get_xlim()[1], color='black',
+ linestyle='--')
+ ax.set_ylabel(ylabel)
+ ax.legend()
+ return ax
+
+# Define graphical parameters
+g_params = {'alpha': 0.7}
+b_params = {'color':'grey', 'alpha': 0.2}
+t_params = {'color':'grey', 'fontsize': 9,
+ 'va':'center', 'ha':'center'}
+```
+
+Here we compare the GDP growth rate of developed economies and developing economies.
+
+```{code-cell} ipython3
+---
+tags: [hide-input]
+---
+
+# Obtain GDP growth rate for a list of countries
+gdp_growth = wb.data.DataFrame('NY.GDP.MKTP.KD.ZG',
+ ['CHN', 'USA', 'DEU', 'BRA', 'ARG', 'GBR', 'JPN', 'MEX'],
+ labels=True)
+gdp_growth = gdp_growth.set_index('Country')
+gdp_growth.columns = gdp_growth.columns.str.replace('YR', '').astype(int)
+
+```
+
+We use the United Kingdom, United States, Germany, and Japan as examples of developed economies.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Developed economies (GDP growth rate %)"
+ name: adv_gdp
+tags: [hide-input]
+---
+
+fig, ax = plt.subplots()
+countries = ['United Kingdom', 'United States', 'Germany', 'Japan']
+ylabel = 'GDP growth rate (%)'
+plot_comparison(gdp_growth.loc[countries, 1962:],
+ countries, ylabel,
+ 0.1, 20, ax,
+ g_params, b_params, t_params)
+plt.show()
+```
+
+We choose Brazil, China, Argentina, and Mexico as representative developing economies.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Developing economies (GDP growth rate %)"
+ name: deve_gdp
+tags: [hide-input]
+---
+
+fig, ax = plt.subplots()
+countries = ['Brazil', 'China', 'Argentina', 'Mexico']
+plot_comparison(gdp_growth.loc[countries, 1962:],
+ countries, ylabel,
+ 0.1, 20, ax,
+ g_params, b_params, t_params)
+plt.show()
+```
+
+
+The comparison of GDP growth rates above suggests that
+business cycles are becoming more synchronized in 21st-century recessions.
+
+However, emerging and less developed economies often experience more volatile
+changes throughout the economic cycles.
+
+Despite the synchronization in GDP growth, the experience of individual countries during
+the recession often differs.
+
+We use the unemployment rate and the recovery of labor market conditions
+as another example.
+
+Here we compare the unemployment rate of the United States,
+the United Kingdom, Japan, and France.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Developed economies (unemployment rate %)"
+ name: adv_unemp
+tags: [hide-input]
+---
+
+unempl_rate = wb.data.DataFrame('SL.UEM.TOTL.NE.ZS',
+ ['USA', 'FRA', 'GBR', 'JPN'], labels=True)
+unempl_rate = unempl_rate.set_index('Country')
+unempl_rate.columns = unempl_rate.columns.str.replace('YR', '').astype(int)
+
+fig, ax = plt.subplots()
+
+countries = ['United Kingdom', 'United States', 'Japan', 'France']
+ylabel = 'unemployment rate (national estimate) (%)'
+plot_comparison(unempl_rate, countries,
+ ylabel, 0.05, None, ax, g_params,
+ b_params, t_params, baseline=None)
+plt.show()
+```
+
+We see that France, with its strong labor unions, typically experiences
+relatively slow labor market recoveries after negative shocks.
+
+We also notice that Japan has a history of very low and stable unemployment rates.
+
+
+## Leading indicators and correlated factors
+
+Examining leading indicators and correlated factors helps policymakers to
+understand the causes and results of business cycles.
+
+We will discuss potential leading indicators and correlated factors from three
+perspectives: consumption, production, and credit level.
+
+
+### Consumption
+
+Consumption depends on consumers' confidence towards their
+income and the overall performance of the economy in the future.
+
+One widely cited indicator for consumer confidence is the [consumer sentiment index](https://fred.stlouisfed.org/series/UMCSENT) published by the University
+of Michigan.
+
+Here we plot the University of Michigan Consumer Sentiment Index and
+year-on-year
+[core consumer price index](https://fred.stlouisfed.org/series/CPILFESL)
+(CPI) change from 1978-2022 in the US.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Consumer sentiment index and YoY CPI change, US"
+ name: csicpi
+tags: [hide-input]
+---
+
+start_date = datetime.datetime(1978, 1, 1)
+end_date = datetime.datetime(2022, 12, 31)
+
+# Limit the plot to a specific range
+start_date_graph = datetime.datetime(1977, 1, 1)
+end_date_graph = datetime.datetime(2023, 12, 31)
+
+nber = web.DataReader('USREC', 'fred', start_date, end_date)
+consumer_confidence = web.DataReader('UMCSENT', 'fred',
+ start_date, end_date)
+
+fig, ax = plt.subplots()
+ax.plot(consumer_confidence, **g_params,
+ color='#377eb8', linestyle='-',
+ linewidth=2)
+ax.fill_between(nber.index, 0, 1,
+ where=nber['USREC']==1,
+ color='grey', edgecolor='none',
+ alpha=0.3,
+ transform=ax.get_xaxis_transform(),
+ label='NBER recession indicators')
+ax.set_ylim([0, ax.get_ylim()[1]])
+ax.set_ylabel('consumer sentiment index')
+
+# Plot CPI on another y-axis
+ax_t = ax.twinx()
+inflation = web.DataReader('CPILFESL', 'fred',
+ start_date, end_date).pct_change(12)*100
+
+# Add CPI on the legend without drawing the line again
+ax_t.plot(2020, 0, **g_params, linestyle='-',
+ linewidth=2, label='consumer sentiment index')
+ax_t.plot(inflation, **g_params,
+ color='#ff7f00', linestyle='--',
+ linewidth=2, label='CPI YoY change (%)')
+
+ax_t.fill_between(nber.index, 0, 1,
+ where=nber['USREC']==1,
+ color='grey', edgecolor='none',
+ alpha=0.3,
+ transform=ax.get_xaxis_transform(),
+ label='NBER recession indicators')
+ax_t.set_ylim([0, ax_t.get_ylim()[1]])
+ax_t.set_xlim([start_date_graph, end_date_graph])
+ax_t.legend(loc='upper center',
+ bbox_to_anchor=(0.5, 1.1),
+ ncol=3, fontsize=9)
+ax_t.set_ylabel('CPI YoY change (%)')
+plt.show()
+```
+
+We see that
+
+* consumer sentiment often remains high during expansions and
+drops before recessions.
+* there is a clear negative correlation between consumer sentiment and the CPI.
+
+When the price of consumer commodities rises, consumer confidence diminishes.
+
+This trend is more significant during [stagflation](https://en.wikipedia.org/wiki/Stagflation).
+
+
+
+### Production
+
+Real industrial output is highly correlated with recessions in the economy.
+
+However, it is not a leading indicator, as the peak of contraction in production
+is delayed relative to consumer confidence and inflation.
+
+We plot the real industrial output change from the previous year
+from 1919 to 2022 in the US to show this trend.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "YoY real output change, US (%)"
+ name: roc
+tags: [hide-input]
+---
+
+start_date = datetime.datetime(1919, 1, 1)
+end_date = datetime.datetime(2022, 12, 31)
+
+nber = web.DataReader('USREC', 'fred',
+ start_date, end_date)
+industrial_output = web.DataReader('INDPRO', 'fred',
+ start_date, end_date).pct_change(12)*100
+
+fig, ax = plt.subplots()
+ax.plot(industrial_output, **g_params,
+ color='#377eb8', linestyle='-',
+ linewidth=2, label='Industrial production index')
+ax.fill_between(nber.index, 0, 1,
+ where=nber['USREC']==1,
+ color='grey', edgecolor='none',
+ alpha=0.3,
+ transform=ax.get_xaxis_transform(),
+ label='NBER recession indicators')
+ax.set_ylim([ax.get_ylim()[0], ax.get_ylim()[1]])
+ax.set_ylabel('YoY real output change (%)')
+plt.show()
+```
+
+We observe the delayed contraction in the plot across recessions.
+
+
+### Credit level
+
+Credit contractions often occur during recessions, as lenders become more
+cautious and borrowers become more hesitant to take on additional debt.
+
+This is due to factors such as a decrease in overall economic
+activity and gloomy expectations for the future.
+
+One example is domestic credit to the private sector by banks in the UK.
+
+The following graph shows the domestic credit to the private sector as a
+percentage of GDP by banks from 1970 to 2022 in the UK.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Domestic credit to private sector by banks (% of GDP)"
+ name: dcpc
+tags: [hide-input]
+---
+
+private_credit = wb.data.DataFrame('FS.AST.PRVT.GD.ZS',
+ ['GBR'], labels=True)
+private_credit = private_credit.set_index('Country')
+private_credit.columns = private_credit.columns.str.replace('YR', '').astype(int)
+
+fig, ax = plt.subplots()
+
+countries = 'United Kingdom'
+ylabel = 'credit level (% of GDP)'
+ax = plot_series(private_credit, countries,
+ ylabel, 0.05, ax, g_params, b_params,
+ t_params, ylim=None, baseline=None)
+plt.show()
+```
+
+Note that the credit rises during economic expansions
+and stagnates or even contracts after recessions.
diff --git a/book/_build/html/_sources/cagan_adaptive.ipynb b/book/_build/html/_sources/cagan_adaptive.ipynb
new file mode 100644
index 0000000..937efbd
--- /dev/null
+++ b/book/_build/html/_sources/cagan_adaptive.ipynb
@@ -0,0 +1,548 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "ec9c9875",
+ "metadata": {},
+ "source": [
+ "# Monetarist Theory of Price Levels with Adaptive Expectations\n",
+ "\n",
+ "## Overview\n",
+ "\n",
+ "\n",
+ "This lecture is a sequel or prequel to {doc}`cagan_ree`.\n",
+ "\n",
+ "We'll use linear algebra to do some experiments with an alternative \"monetarist\" or \"fiscal\" theory of price levels.\n",
+ "\n",
+ "Like the model in {doc}`cagan_ree`, the model asserts that when a government persistently spends more than it collects in taxes and prints money to finance the shortfall, it puts upward pressure on the price level and generates persistent inflation.\n",
+ "\n",
+ "Instead of the \"perfect foresight\" or \"rational expectations\" version of the model in {doc}`cagan_ree`, our model in the present lecture is an \"adaptive expectations\" version of a model that {cite}`Cagan` used to study the monetary dynamics of hyperinflations. \n",
+ "\n",
+ "It combines these components:\n",
+ "\n",
+ "* a demand function for real money balances that asserts that the logarithm of the quantity of real balances demanded depends inversely on the public's expected rate of inflation\n",
+ "\n",
+ "* an **adaptive expectations** model that describes how the public's anticipated rate of inflation responds to past values of actual inflation\n",
+ "\n",
+ "* an equilibrium condition that equates the demand for money to the supply\n",
+ "\n",
+ "* an exogenous sequence of rates of growth of the money supply\n",
+ "\n",
+ "Our model stays quite close to Cagan's original specification. \n",
+ "\n",
+ "As in {doc}`pv` and {doc}`cons_smooth`, the only linear algebra operations that we'll be using are matrix multiplication and matrix inversion.\n",
+ "\n",
+ "To facilitate using linear matrix algebra as our principal mathematical tool, we'll use a finite horizon version of\n",
+ "the model.\n",
+ "\n",
+ "## Structure of the model\n",
+ "\n",
+ "Let \n",
+ "\n",
+ "* $ m_t $ be the log of the supply of nominal money balances;\n",
+ "* $\\mu_t = m_{t+1} - m_t $ be the net rate of growth of nominal balances;\n",
+ "* $p_t $ be the log of the price level;\n",
+ "* $\\pi_t = p_{t+1} - p_t $ be the net rate of inflation between $t$ and $ t+1$;\n",
+ "* $\\pi_t^*$ be the public's expected rate of inflation between $t$ and $t+1$;\n",
+ "* $T$ the horizon -- i.e., the last period for which the model will determine $p_t$\n",
+ "* $\\pi_0^*$ public's initial expected rate of inflation between time $0$ and time $1$.\n",
+ " \n",
+ " \n",
+ "The demand for real balances $\\exp\\left(m_t^d-p_t\\right)$ is governed by the following version of the Cagan demand function\n",
+ " \n",
+ "$$ \n",
+ "m_t^d - p_t = -\\alpha \\pi_t^* \\: , \\: \\alpha > 0 ; \\quad t = 0, 1, \\ldots, T .\n",
+ "$$ (eq:caganmd_ad)\n",
+ "\n",
+ "\n",
+ "This equation asserts that the demand for real balances\n",
+ "is inversely related to the public's expected rate of inflation with sensitivity $\\alpha$.\n",
+ "\n",
+ "Equating the logarithm $m_t^d$ of the demand for money to the logarithm $m_t$ of the supply of money in equation {eq}`eq:caganmd_ad` and solving for the logarithm $p_t$\n",
+ "of the price level gives\n",
+ "\n",
+ "$$\n",
+ "p_t = m_t + \\alpha \\pi_t^*\n",
+ "$$ (eq:eqfiscth1)\n",
+ "\n",
+ "Taking the difference between equation {eq}`eq:eqfiscth1` at time $t+1$ and at time \n",
+ "$t$ gives\n",
+ "\n",
+ "$$\n",
+ "\\pi_t = \\mu_t + \\alpha \\pi_{t+1}^* - \\alpha \\pi_t^*\n",
+ "$$ (eq:eq%pipi)\n",
+ "\n",
+ "We assume that the expected rate of inflation $\\pi_t^*$ is governed\n",
+ "by the following adaptive expectations scheme proposed by {cite}`Friedman1956` and {cite}`Cagan`, where $\\lambda\\in [0,1]$ denotes the weight on expected inflation.\n",
+ "\n",
+ "$$\n",
+ "\\pi_{t+1}^* = \\lambda \\pi_t^* + (1 -\\lambda) \\pi_t \n",
+ "$$ (eq:adaptexpn)\n",
+ "\n",
+ "As exogenous inputs into the model, we take initial conditions $m_0, \\pi_0^*$\n",
+ "and a money growth sequence $\\mu = \\{\\mu_t\\}_{t=0}^T$. \n",
+ "\n",
+ "As endogenous outputs of our model we want to find sequences $\\pi = \\{\\pi_t\\}_{t=0}^T, p = \\{p_t\\}_{t=0}^T$ as functions of the exogenous inputs.\n",
+ "\n",
+ "We'll do some mental experiments by studying how the model outputs vary as we vary\n",
+ "the model inputs.\n",
+ "\n",
+ "## Representing key equations with linear algebra\n",
+ "\n",
+ "We begin by writing the equation {eq}`eq:adaptexpn` adaptive expectations model for $\\pi_t^*$ for $t=0, \\ldots, T$ as\n",
+ "\n",
+ "$$\n",
+ "\\begin{bmatrix} 1 & 0 & 0 & \\cdots & 0 & 0 \\cr\n",
+ "-\\lambda & 1 & 0 & \\cdots & 0 & 0 \\cr\n",
+ "0 & - \\lambda & 1 & \\cdots & 0 & 0 \\cr\n",
+ "\\vdots & \\vdots & \\vdots & \\cdots & \\vdots & \\vdots \\cr\n",
+ "0 & 0 & 0 & \\cdots & -\\lambda & 1\n",
+ "\\end{bmatrix}\n",
+ "\\begin{bmatrix} \\pi_0^* \\cr\n",
+ " \\pi_1^* \\cr\n",
+ " \\pi_2^* \\cr\n",
+ " \\vdots \\cr\n",
+ " \\pi_{T+1}^* \n",
+ " \\end{bmatrix} =\n",
+ " (1-\\lambda) \\begin{bmatrix} \n",
+ " 0 & 0 & 0 & \\cdots & 0 \\cr\n",
+ " 1 & 0 & 0 & \\cdots & 0 \\cr\n",
+ " 0 & 1 & 0 & \\cdots & 0 \\cr\n",
+ " \\vdots &\\vdots & \\vdots & \\cdots & \\vdots \\cr\n",
+ " 0 & 0 & 0 & \\cdots & 1 \\end{bmatrix}\n",
+ " \\begin{bmatrix}\\pi_0 \\cr \\pi_1 \\cr \\pi_2 \\cr \\vdots \\cr \\pi_T\n",
+ " \\end{bmatrix} +\n",
+ " \\begin{bmatrix} \\pi_0^* \\cr 0 \\cr 0 \\cr \\vdots \\cr 0 \\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "Write this equation as\n",
+ "\n",
+ "$$\n",
+ " A \\pi^* = (1-\\lambda) B \\pi + \\pi_0^*\n",
+ "$$ (eq:eq1)\n",
+ "\n",
+ "where the $(T+2) \\times (T+2) $matrix $A$, the $(T+2)\\times (T+1)$ matrix $B$, and the vectors $\\pi^* , \\pi_0, \\pi_0^*$\n",
+ "are defined implicitly by aligning these two equations.\n",
+ "\n",
+ "Next we write the key equation {eq}`eq:eq%pipi` in matrix notation as\n",
+ "\n",
+ "$$ \n",
+ "\\begin{bmatrix}\n",
+ "\\pi_0 \\cr \\pi_1 \\cr \\pi_1 \\cr \\vdots \\cr \\pi_T \\end{bmatrix}\n",
+ "= \\begin{bmatrix}\n",
+ "\\mu_0 \\cr \\mu_1 \\cr \\mu_2 \\cr \\vdots \\cr \\mu_T \\end{bmatrix}\n",
+ "+ \\begin{bmatrix} - \\alpha & \\alpha & 0 & \\cdots & 0 & 0 \\cr\n",
+ "0 & -\\alpha & \\alpha & \\cdots & 0 & 0 \\cr\n",
+ "0 & 0 & -\\alpha & \\cdots & 0 & 0 \\cr\n",
+ "\\vdots & \\vdots & \\vdots & \\cdots & \\alpha & 0 \\cr\n",
+ "0 & 0 & 0 & \\cdots & -\\alpha & \\alpha \n",
+ "\\end{bmatrix}\n",
+ "\\begin{bmatrix} \\pi_0^* \\cr\n",
+ " \\pi_1^* \\cr\n",
+ " \\pi_2^* \\cr\n",
+ " \\vdots \\cr\n",
+ " \\pi_{T+1}^* \n",
+ " \\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "Represent the previous equation system in terms of vectors and matrices as\n",
+ "\n",
+ "$$\n",
+ "\\pi = \\mu + C \\pi^*\n",
+ "$$ (eq:eq2)\n",
+ "\n",
+ "where the $(T+1) \\times (T+2)$ matrix $C$ is defined implicitly to align this equation with the preceding\n",
+ "equation system.\n",
+ "\n",
+ "## Harvesting insights from our matrix formulation\n",
+ "\n",
+ "We now have all of the ingredients we need to solve for $\\pi$ as\n",
+ "a function of $\\mu, \\pi_0, \\pi_0^*$. \n",
+ "\n",
+ "Combine equations {eq}`eq:eq1`and {eq}`eq:eq2` to get\n",
+ "\n",
+ "$$\n",
+ "\\begin{aligned}\n",
+ "A \\pi^* & = (1-\\lambda) B \\pi + \\pi_0^* \\cr\n",
+ " & = (1-\\lambda) B \\left[ \\mu + C \\pi^* \\right] + \\pi_0^*\n",
+ "\\end{aligned}\n",
+ "$$\n",
+ "\n",
+ "which implies that\n",
+ "\n",
+ "$$\n",
+ "\\left[ A - (1-\\lambda) B C \\right] \\pi^* = (1-\\lambda) B \\mu+ \\pi_0^*\n",
+ "$$\n",
+ "\n",
+ "Multiplying both sides of the above equation by the inverse of the matrix on the left side gives\n",
+ "\n",
+ "$$\n",
+ "\\pi^* = \\left[ A - (1-\\lambda) B C \\right]^{-1} \\left[ (1-\\lambda) B \\mu+ \\pi_0^* \\right]\n",
+ "$$ (eq:eq4)\n",
+ "\n",
+ "Having solved equation {eq}`eq:eq4` for $\\pi^*$, we can use equation {eq}`eq:eq2` to solve for $\\pi$:\n",
+ "\n",
+ "$$\n",
+ "\\pi = \\mu + C \\pi^*\n",
+ "$$\n",
+ "\n",
+ "\n",
+ "We have thus solved for two of the key endogenous time series determined by our model, namely, the sequence $\\pi^*$\n",
+ "of expected inflation rates and the sequence $\\pi$ of actual inflation rates. \n",
+ "\n",
+ "Knowing these, we can then quickly calculate the associated sequence $p$ of the logarithm of the price level\n",
+ "from equation {eq}`eq:eqfiscth1`. \n",
+ "\n",
+ "Let's fill in the details for this step.\n",
+ "\n",
+ "Since we now know $\\mu$ it is easy to compute $m$.\n",
+ "\n",
+ "Thus, notice that we can represent the equations \n",
+ "\n",
+ "$$ \n",
+ "m_{t+1} = m_t + \\mu_t , \\quad t = 0, 1, \\ldots, T\n",
+ "$$\n",
+ "\n",
+ "as the matrix equation\n",
+ "\n",
+ "$$\n",
+ "\\begin{bmatrix}\n",
+ "1 & 0 & 0 & \\cdots & 0 & 0 \\cr\n",
+ "-1 & 1 & 0 & \\cdots & 0 & 0 \\cr\n",
+ "0 & -1 & 1 & \\cdots & 0 & 0 \\cr\n",
+ "\\vdots & \\vdots & \\vdots & \\vdots & 0 & 0 \\cr\n",
+ "0 & 0 & 0 & \\cdots & 1 & 0 \\cr\n",
+ "0 & 0 & 0 & \\cdots & -1 & 1 \n",
+ "\\end{bmatrix}\n",
+ "\\begin{bmatrix} \n",
+ "m_1 \\cr m_2 \\cr m_3 \\cr \\vdots \\cr m_T \\cr m_{T+1}\n",
+ "\\end{bmatrix}\n",
+ "= \\begin{bmatrix} \n",
+ "\\mu_0 \\cr \\mu_1 \\cr \\mu_2 \\cr \\vdots \\cr \\mu_{T-1} \\cr \\mu_T\n",
+ "\\end{bmatrix}\n",
+ "+ \\begin{bmatrix} \n",
+ "m_0 \\cr 0 \\cr 0 \\cr \\vdots \\cr 0 \\cr 0\n",
+ "\\end{bmatrix}\n",
+ "$$ (eq:eq101_ad)\n",
+ "\n",
+ "Multiplying both sides of equation {eq}`eq:eq101_ad` with the inverse of the matrix on the left will give \n",
+ "\n",
+ "$$\n",
+ "m_t = m_0 + \\sum_{s=0}^{t-1} \\mu_s, \\quad t =1, \\ldots, T+1\n",
+ "$$ (eq:mcum_ad)\n",
+ "\n",
+ "Equation {eq}`eq:mcum_ad` shows that the log of the money supply at $t$ equals the log $m_0$ of the initial money supply \n",
+ "plus accumulation of rates of money growth between times $0$ and $t$.\n",
+ "\n",
+ "We can then compute $p_t$ for each $t$ from equation {eq}`eq:eqfiscth1`.\n",
+ "\n",
+ "We can write a compact formula for $p $ as\n",
+ "\n",
+ "$$ \n",
+ "p = m + \\alpha \\hat \\pi^*\n",
+ "$$\n",
+ "\n",
+ "where \n",
+ "\n",
+ "$$\n",
+ "\\hat \\pi^* = \\begin{bmatrix} \\pi_0^* \\cr\n",
+ " \\pi_1^* \\cr\n",
+ " \\pi_2^* \\cr\n",
+ " \\vdots \\cr\n",
+ " \\pi_{T}^* \n",
+ " \\end{bmatrix},\n",
+ " $$\n",
+ "\n",
+ "which is just $\\pi^*$ with the last element dropped.\n",
+ " \n",
+ "## Forecast errors and model computation\n",
+ "\n",
+ "Our computations will verify that \n",
+ "\n",
+ "$$\n",
+ "\\hat \\pi^* \\neq \\pi,\n",
+ "$$\n",
+ "\n",
+ "so that in general\n",
+ "\n",
+ "$$ \n",
+ "\\pi_t^* \\neq \\pi_t, \\quad t = 0, 1, \\ldots , T\n",
+ "$$ (eq:notre)\n",
+ "\n",
+ "This outcome is typical in models in which adaptive expectations hypothesis like equation {eq}`eq:adaptexpn` appear as a\n",
+ "component. \n",
+ "\n",
+ "In {doc}`cagan_ree`, we studied a version of the model that replaces hypothesis {eq}`eq:adaptexpn` with\n",
+ "a \"perfect foresight\" or \"rational expectations\" hypothesis.\n",
+ "\n",
+ "But now, let's dive in and do some computations with the adaptive expectations version of the model.\n",
+ "\n",
+ "As usual, we'll start by importing some Python modules."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a81435c9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "from collections import namedtuple\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "882cca45",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Cagan_Adaptive = namedtuple(\"Cagan_Adaptive\", \n",
+ " [\"α\", \"m0\", \"Eπ0\", \"T\", \"λ\"])\n",
+ "\n",
+ "def create_cagan_adaptive_model(α = 5, m0 = 1, Eπ0 = 0.5, T=80, λ = 0.9):\n",
+ " return Cagan_Adaptive(α, m0, Eπ0, T, λ)\n",
+ "\n",
+ "md = create_cagan_adaptive_model()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "08b24fa4",
+ "metadata": {
+ "user_expressions": []
+ },
+ "source": [
+ "We solve the model and plot variables of interests using the following functions."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "08e871f5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def solve_cagan_adaptive(model, μ_seq):\n",
+ " \" Solve the Cagan model in finite time. \"\n",
+ " α, m0, Eπ0, T, λ = model\n",
+ " \n",
+ " A = np.eye(T+2, T+2) - λ*np.eye(T+2, T+2, k=-1)\n",
+ " B = np.eye(T+2, T+1, k=-1)\n",
+ " C = -α*np.eye(T+1, T+2) + α*np.eye(T+1, T+2, k=1)\n",
+ " Eπ0_seq = np.append(Eπ0, np.zeros(T+1))\n",
+ "\n",
+ " # Eπ_seq is of length T+2\n",
+ " Eπ_seq = np.linalg.solve(A - (1-λ)*B @ C, (1-λ) * B @ μ_seq + Eπ0_seq)\n",
+ "\n",
+ " # π_seq is of length T+1\n",
+ " π_seq = μ_seq + C @ Eπ_seq\n",
+ "\n",
+ " D = np.eye(T+1, T+1) - np.eye(T+1, T+1, k=-1) # D is the coefficient matrix in Equation (14.8)\n",
+ " m0_seq = np.append(m0, np.zeros(T))\n",
+ "\n",
+ " # m_seq is of length T+2\n",
+ " m_seq = np.linalg.solve(D, μ_seq + m0_seq)\n",
+ " m_seq = np.append(m0, m_seq)\n",
+ "\n",
+ " # p_seq is of length T+2\n",
+ " p_seq = m_seq + α * Eπ_seq\n",
+ "\n",
+ " return π_seq, Eπ_seq, m_seq, p_seq"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "cc0bc6f9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def solve_and_plot(model, μ_seq):\n",
+ " \n",
+ " π_seq, Eπ_seq, m_seq, p_seq = solve_cagan_adaptive(model, μ_seq)\n",
+ " \n",
+ " T_seq = range(model.T+2)\n",
+ " \n",
+ " fig, ax = plt.subplots(5, 1, figsize=[5, 12], dpi=200)\n",
+ " ax[0].plot(T_seq[:-1], μ_seq)\n",
+ " ax[1].plot(T_seq[:-1], π_seq, label=r'$\\pi_t$')\n",
+ " ax[1].plot(T_seq, Eπ_seq, label=r'$\\pi^{*}_{t}$')\n",
+ " ax[2].plot(T_seq, m_seq - p_seq)\n",
+ " ax[3].plot(T_seq, m_seq)\n",
+ " ax[4].plot(T_seq, p_seq)\n",
+ " \n",
+ " y_labs = [r'$\\mu$', r'$\\pi$', r'$m - p$', r'$m$', r'$p$']\n",
+ " subplot_title = [r'Money supply growth', r'Inflation', r'Real balances', r'Money supply', r'Price level']\n",
+ "\n",
+ " for i in range(5):\n",
+ " ax[i].set_xlabel(r'$t$')\n",
+ " ax[i].set_ylabel(y_labs[i])\n",
+ " ax[i].set_title(subplot_title[i])\n",
+ "\n",
+ " ax[1].legend()\n",
+ " plt.tight_layout()\n",
+ " plt.show()\n",
+ " \n",
+ " return π_seq, Eπ_seq, m_seq, p_seq"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "77b89a45",
+ "metadata": {
+ "user_expressions": []
+ },
+ "source": [
+ "## Technical condition for stability\n",
+ "\n",
+ "In constructing our examples, we shall assume that $(\\lambda, \\alpha)$ satisfy\n",
+ "\n",
+ "$$\n",
+ "\\Bigl| \\frac{\\lambda-\\alpha(1-\\lambda)}{1-\\alpha(1-\\lambda)} \\Bigr| < 1\n",
+ "$$ (eq:suffcond)\n",
+ "\n",
+ "The source of this condition is the following string of deductions:\n",
+ "\n",
+ "$$\n",
+ "\\begin{aligned}\n",
+ "\\pi_{t}&=\\mu_{t}+\\alpha\\pi_{t+1}^{*}-\\alpha\\pi_{t}^{*}\\\\\\pi_{t+1}^{*}&=\\lambda\\pi_{t}^{*}+(1-\\lambda)\\pi_{t}\\\\\\pi_{t}&=\\frac{\\mu_{t}}{1-\\alpha(1-\\lambda)}-\\frac{\\alpha(1-\\lambda)}{1-\\alpha(1-\\lambda)}\\pi_{t}^{*}\\\\\\implies\\pi_{t}^{*}&=\\frac{1}{\\alpha(1-\\lambda)}\\mu_{t}-\\frac{1-\\alpha(1-\\lambda)}{\\alpha(1-\\lambda)}\\pi_{t}\\\\\\pi_{t+1}&=\\frac{\\mu_{t+1}}{1-\\alpha(1-\\lambda)}-\\frac{\\alpha(1-\\lambda)}{1-\\alpha(1-\\lambda)}\\left(\\lambda\\pi_{t}^{*}+(1-\\lambda)\\pi_{t}\\right)\\\\&=\\frac{\\mu_{t+1}}{1-\\alpha(1-\\lambda)}-\\frac{\\lambda}{1-\\alpha(1-\\lambda)}\\mu_{t}+\\frac{\\lambda-\\alpha(1-\\lambda)}{1-\\alpha(1-\\lambda)}\\pi_{t}\n",
+ "\\end{aligned}\n",
+ "$$\n",
+ "\n",
+ "By assuring that the coefficient on $\\pi_t$ is less than one in absolute value, condition {eq}`eq:suffcond` assures stability of the dynamics of $\\{\\pi_t\\}$ described by the last line of our string of deductions. \n",
+ "\n",
+ "The reader is free to study outcomes in examples that violate condition {eq}`eq:suffcond`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "44369819",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(np.abs((md.λ - md.α*(1-md.λ))/(1 - md.α*(1-md.λ))))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2bf89ede",
+ "metadata": {},
+ "source": [
+ "## Experiments\n",
+ "\n",
+ "Now we'll turn to some experiments.\n",
+ "\n",
+ "### Experiment 1\n",
+ "\n",
+ "We'll study a situation in which the rate of growth of the money supply is $\\mu_0$\n",
+ "from $t=0$ to $t= T_1$ and then permanently falls to $\\mu^*$ at $t=T_1$.\n",
+ "\n",
+ "Thus, let $T_1 \\in (0, T)$. \n",
+ "\n",
+ "So where $\\mu_0 > \\mu^*$, we assume that\n",
+ "\n",
+ "$$\n",
+ "\\mu_{t} = \\begin{cases}\n",
+ " \\mu_0 , & t = 0, \\ldots, T_1 -1 \\\\\n",
+ " \\mu^* , & t \\geq T_1\n",
+ " \\end{cases}\n",
+ "$$\n",
+ "\n",
+ "Notice that we studied exactly this experiment in a rational expectations version of the model in {doc}`cagan_ree`.\n",
+ "\n",
+ "So by comparing outcomes across the two lectures, we can learn about consequences of assuming adaptive expectations, as we do here, instead of rational expectations as we assumed in that other lecture."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bebb9444",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Parameters for the experiment 1\n",
+ "T1 = 60\n",
+ "μ0 = 0.5\n",
+ "μ_star = 0\n",
+ "\n",
+ "μ_seq_1 = np.append(μ0*np.ones(T1), μ_star*np.ones(md.T+1-T1))\n",
+ "\n",
+ "# solve and plot\n",
+ "π_seq_1, Eπ_seq_1, m_seq_1, p_seq_1 = solve_and_plot(md, μ_seq_1)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "403379b7",
+ "metadata": {},
+ "source": [
+ "We invite the reader to compare outcomes with those under rational expectations studied in {doc}`cagan_ree`.\n",
+ "\n",
+ "Please note how the actual inflation rate $\\pi_t$ \"overshoots\" its ultimate steady-state value at the time of the sudden reduction in the rate of growth of the money supply at time $T_1$.\n",
+ "\n",
+ "We invite you to explain to yourself the source of this overshooting and why it does not occur in the rational expectations version of the model.\n",
+ "\n",
+ "### Experiment 2\n",
+ "\n",
+ "Now we'll do a different experiment, namely, a gradual stabilization in which the rate of growth of the money supply smoothly \n",
+ "decline from a high value to a persistently low value. \n",
+ "\n",
+ "While price level inflation eventually falls, it falls more slowly than the driving force that ultimately causes it to fall, namely, the falling rate of growth of the money supply.\n",
+ "\n",
+ "The sluggish fall in inflation is explained by how anticipated inflation $\\pi_t^*$ persistently exceeds actual inflation $\\pi_t$ during the transition from a high inflation to a low inflation situation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d58b285b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# parameters\n",
+ "ϕ = 0.9\n",
+ "μ_seq_2 = np.array([ϕ**t * μ0 + (1-ϕ**t)*μ_star for t in range(md.T)])\n",
+ "μ_seq_2 = np.append(μ_seq_2, μ_star)\n",
+ "\n",
+ "\n",
+ "# solve and plot\n",
+ "π_seq_2, Eπ_seq_2, m_seq_2, p_seq_2 = solve_and_plot(md, μ_seq_2)"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.14.5"
+ }
+ },
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "source_map": [
+ 12,
+ 288,
+ 294,
+ 303,
+ 307,
+ 338,
+ 368,
+ 392,
+ 394,
+ 420,
+ 430,
+ 447
+ ]
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/cagan_adaptive.md b/book/_build/html/_sources/cagan_adaptive.md
new file mode 100644
index 0000000..b8403bf
--- /dev/null
+++ b/book/_build/html/_sources/cagan_adaptive.md
@@ -0,0 +1,456 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.14.5
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+# Monetarist Theory of Price Levels with Adaptive Expectations
+
+## Overview
+
+
+This lecture is a sequel or prequel to {doc}`cagan_ree`.
+
+We'll use linear algebra to do some experiments with an alternative "monetarist" or "fiscal" theory of price levels.
+
+Like the model in {doc}`cagan_ree`, the model asserts that when a government persistently spends more than it collects in taxes and prints money to finance the shortfall, it puts upward pressure on the price level and generates persistent inflation.
+
+Instead of the "perfect foresight" or "rational expectations" version of the model in {doc}`cagan_ree`, our model in the present lecture is an "adaptive expectations" version of a model that {cite}`Cagan` used to study the monetary dynamics of hyperinflations.
+
+It combines these components:
+
+* a demand function for real money balances that asserts that the logarithm of the quantity of real balances demanded depends inversely on the public's expected rate of inflation
+
+* an **adaptive expectations** model that describes how the public's anticipated rate of inflation responds to past values of actual inflation
+
+* an equilibrium condition that equates the demand for money to the supply
+
+* an exogenous sequence of rates of growth of the money supply
+
+Our model stays quite close to Cagan's original specification.
+
+As in {doc}`pv` and {doc}`cons_smooth`, the only linear algebra operations that we'll be using are matrix multiplication and matrix inversion.
+
+To facilitate using linear matrix algebra as our principal mathematical tool, we'll use a finite horizon version of
+the model.
+
+## Structure of the model
+
+Let
+
+* $ m_t $ be the log of the supply of nominal money balances;
+* $\mu_t = m_{t+1} - m_t $ be the net rate of growth of nominal balances;
+* $p_t $ be the log of the price level;
+* $\pi_t = p_{t+1} - p_t $ be the net rate of inflation between $t$ and $ t+1$;
+* $\pi_t^*$ be the public's expected rate of inflation between $t$ and $t+1$;
+* $T$ the horizon -- i.e., the last period for which the model will determine $p_t$
+* $\pi_0^*$ public's initial expected rate of inflation between time $0$ and time $1$.
+
+
+The demand for real balances $\exp\left(m_t^d-p_t\right)$ is governed by the following version of the Cagan demand function
+
+$$
+m_t^d - p_t = -\alpha \pi_t^* \: , \: \alpha > 0 ; \quad t = 0, 1, \ldots, T .
+$$ (eq:caganmd_ad)
+
+
+This equation asserts that the demand for real balances
+is inversely related to the public's expected rate of inflation with sensitivity $\alpha$.
+
+Equating the logarithm $m_t^d$ of the demand for money to the logarithm $m_t$ of the supply of money in equation {eq}`eq:caganmd_ad` and solving for the logarithm $p_t$
+of the price level gives
+
+$$
+p_t = m_t + \alpha \pi_t^*
+$$ (eq:eqfiscth1)
+
+Taking the difference between equation {eq}`eq:eqfiscth1` at time $t+1$ and at time
+$t$ gives
+
+$$
+\pi_t = \mu_t + \alpha \pi_{t+1}^* - \alpha \pi_t^*
+$$ (eq:eq%pipi)
+
+We assume that the expected rate of inflation $\pi_t^*$ is governed
+by the following adaptive expectations scheme proposed by {cite}`Friedman1956` and {cite}`Cagan`, where $\lambda\in [0,1]$ denotes the weight on expected inflation.
+
+$$
+\pi_{t+1}^* = \lambda \pi_t^* + (1 -\lambda) \pi_t
+$$ (eq:adaptexpn)
+
+As exogenous inputs into the model, we take initial conditions $m_0, \pi_0^*$
+and a money growth sequence $\mu = \{\mu_t\}_{t=0}^T$.
+
+As endogenous outputs of our model we want to find sequences $\pi = \{\pi_t\}_{t=0}^T, p = \{p_t\}_{t=0}^T$ as functions of the exogenous inputs.
+
+We'll do some mental experiments by studying how the model outputs vary as we vary
+the model inputs.
+
+## Representing key equations with linear algebra
+
+We begin by writing the equation {eq}`eq:adaptexpn` adaptive expectations model for $\pi_t^*$ for $t=0, \ldots, T$ as
+
+$$
+\begin{bmatrix} 1 & 0 & 0 & \cdots & 0 & 0 \cr
+-\lambda & 1 & 0 & \cdots & 0 & 0 \cr
+0 & - \lambda & 1 & \cdots & 0 & 0 \cr
+\vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr
+0 & 0 & 0 & \cdots & -\lambda & 1
+\end{bmatrix}
+\begin{bmatrix} \pi_0^* \cr
+ \pi_1^* \cr
+ \pi_2^* \cr
+ \vdots \cr
+ \pi_{T+1}^*
+ \end{bmatrix} =
+ (1-\lambda) \begin{bmatrix}
+ 0 & 0 & 0 & \cdots & 0 \cr
+ 1 & 0 & 0 & \cdots & 0 \cr
+ 0 & 1 & 0 & \cdots & 0 \cr
+ \vdots &\vdots & \vdots & \cdots & \vdots \cr
+ 0 & 0 & 0 & \cdots & 1 \end{bmatrix}
+ \begin{bmatrix}\pi_0 \cr \pi_1 \cr \pi_2 \cr \vdots \cr \pi_T
+ \end{bmatrix} +
+ \begin{bmatrix} \pi_0^* \cr 0 \cr 0 \cr \vdots \cr 0 \end{bmatrix}
+$$
+
+Write this equation as
+
+$$
+ A \pi^* = (1-\lambda) B \pi + \pi_0^*
+$$ (eq:eq1)
+
+where the $(T+2) \times (T+2) $matrix $A$, the $(T+2)\times (T+1)$ matrix $B$, and the vectors $\pi^* , \pi_0, \pi_0^*$
+are defined implicitly by aligning these two equations.
+
+Next we write the key equation {eq}`eq:eq%pipi` in matrix notation as
+
+$$
+\begin{bmatrix}
+\pi_0 \cr \pi_1 \cr \pi_1 \cr \vdots \cr \pi_T \end{bmatrix}
+= \begin{bmatrix}
+\mu_0 \cr \mu_1 \cr \mu_2 \cr \vdots \cr \mu_T \end{bmatrix}
++ \begin{bmatrix} - \alpha & \alpha & 0 & \cdots & 0 & 0 \cr
+0 & -\alpha & \alpha & \cdots & 0 & 0 \cr
+0 & 0 & -\alpha & \cdots & 0 & 0 \cr
+\vdots & \vdots & \vdots & \cdots & \alpha & 0 \cr
+0 & 0 & 0 & \cdots & -\alpha & \alpha
+\end{bmatrix}
+\begin{bmatrix} \pi_0^* \cr
+ \pi_1^* \cr
+ \pi_2^* \cr
+ \vdots \cr
+ \pi_{T+1}^*
+ \end{bmatrix}
+$$
+
+Represent the previous equation system in terms of vectors and matrices as
+
+$$
+\pi = \mu + C \pi^*
+$$ (eq:eq2)
+
+where the $(T+1) \times (T+2)$ matrix $C$ is defined implicitly to align this equation with the preceding
+equation system.
+
+## Harvesting insights from our matrix formulation
+
+We now have all of the ingredients we need to solve for $\pi$ as
+a function of $\mu, \pi_0, \pi_0^*$.
+
+Combine equations {eq}`eq:eq1`and {eq}`eq:eq2` to get
+
+$$
+\begin{aligned}
+A \pi^* & = (1-\lambda) B \pi + \pi_0^* \cr
+ & = (1-\lambda) B \left[ \mu + C \pi^* \right] + \pi_0^*
+\end{aligned}
+$$
+
+which implies that
+
+$$
+\left[ A - (1-\lambda) B C \right] \pi^* = (1-\lambda) B \mu+ \pi_0^*
+$$
+
+Multiplying both sides of the above equation by the inverse of the matrix on the left side gives
+
+$$
+\pi^* = \left[ A - (1-\lambda) B C \right]^{-1} \left[ (1-\lambda) B \mu+ \pi_0^* \right]
+$$ (eq:eq4)
+
+Having solved equation {eq}`eq:eq4` for $\pi^*$, we can use equation {eq}`eq:eq2` to solve for $\pi$:
+
+$$
+\pi = \mu + C \pi^*
+$$
+
+
+We have thus solved for two of the key endogenous time series determined by our model, namely, the sequence $\pi^*$
+of expected inflation rates and the sequence $\pi$ of actual inflation rates.
+
+Knowing these, we can then quickly calculate the associated sequence $p$ of the logarithm of the price level
+from equation {eq}`eq:eqfiscth1`.
+
+Let's fill in the details for this step.
+
+Since we now know $\mu$ it is easy to compute $m$.
+
+Thus, notice that we can represent the equations
+
+$$
+m_{t+1} = m_t + \mu_t , \quad t = 0, 1, \ldots, T
+$$
+
+as the matrix equation
+
+$$
+\begin{bmatrix}
+1 & 0 & 0 & \cdots & 0 & 0 \cr
+-1 & 1 & 0 & \cdots & 0 & 0 \cr
+0 & -1 & 1 & \cdots & 0 & 0 \cr
+\vdots & \vdots & \vdots & \vdots & 0 & 0 \cr
+0 & 0 & 0 & \cdots & 1 & 0 \cr
+0 & 0 & 0 & \cdots & -1 & 1
+\end{bmatrix}
+\begin{bmatrix}
+m_1 \cr m_2 \cr m_3 \cr \vdots \cr m_T \cr m_{T+1}
+\end{bmatrix}
+= \begin{bmatrix}
+\mu_0 \cr \mu_1 \cr \mu_2 \cr \vdots \cr \mu_{T-1} \cr \mu_T
+\end{bmatrix}
++ \begin{bmatrix}
+m_0 \cr 0 \cr 0 \cr \vdots \cr 0 \cr 0
+\end{bmatrix}
+$$ (eq:eq101_ad)
+
+Multiplying both sides of equation {eq}`eq:eq101_ad` with the inverse of the matrix on the left will give
+
+$$
+m_t = m_0 + \sum_{s=0}^{t-1} \mu_s, \quad t =1, \ldots, T+1
+$$ (eq:mcum_ad)
+
+Equation {eq}`eq:mcum_ad` shows that the log of the money supply at $t$ equals the log $m_0$ of the initial money supply
+plus accumulation of rates of money growth between times $0$ and $t$.
+
+We can then compute $p_t$ for each $t$ from equation {eq}`eq:eqfiscth1`.
+
+We can write a compact formula for $p $ as
+
+$$
+p = m + \alpha \hat \pi^*
+$$
+
+where
+
+$$
+\hat \pi^* = \begin{bmatrix} \pi_0^* \cr
+ \pi_1^* \cr
+ \pi_2^* \cr
+ \vdots \cr
+ \pi_{T}^*
+ \end{bmatrix},
+ $$
+
+which is just $\pi^*$ with the last element dropped.
+
+## Forecast errors and model computation
+
+Our computations will verify that
+
+$$
+\hat \pi^* \neq \pi,
+$$
+
+so that in general
+
+$$
+\pi_t^* \neq \pi_t, \quad t = 0, 1, \ldots , T
+$$ (eq:notre)
+
+This outcome is typical in models in which adaptive expectations hypothesis like equation {eq}`eq:adaptexpn` appear as a
+component.
+
+In {doc}`cagan_ree`, we studied a version of the model that replaces hypothesis {eq}`eq:adaptexpn` with
+a "perfect foresight" or "rational expectations" hypothesis.
+
+But now, let's dive in and do some computations with the adaptive expectations version of the model.
+
+As usual, we'll start by importing some Python modules.
+
+```{code-cell} ipython3
+import numpy as np
+from collections import namedtuple
+import matplotlib.pyplot as plt
+```
+
+```{code-cell} ipython3
+Cagan_Adaptive = namedtuple("Cagan_Adaptive",
+ ["α", "m0", "Eπ0", "T", "λ"])
+
+def create_cagan_adaptive_model(α = 5, m0 = 1, Eπ0 = 0.5, T=80, λ = 0.9):
+ return Cagan_Adaptive(α, m0, Eπ0, T, λ)
+
+md = create_cagan_adaptive_model()
+```
++++ {"user_expressions": []}
+
+We solve the model and plot variables of interests using the following functions.
+
+```{code-cell} ipython3
+def solve_cagan_adaptive(model, μ_seq):
+ " Solve the Cagan model in finite time. "
+ α, m0, Eπ0, T, λ = model
+
+ A = np.eye(T+2, T+2) - λ*np.eye(T+2, T+2, k=-1)
+ B = np.eye(T+2, T+1, k=-1)
+ C = -α*np.eye(T+1, T+2) + α*np.eye(T+1, T+2, k=1)
+ Eπ0_seq = np.append(Eπ0, np.zeros(T+1))
+
+ # Eπ_seq is of length T+2
+ Eπ_seq = np.linalg.solve(A - (1-λ)*B @ C, (1-λ) * B @ μ_seq + Eπ0_seq)
+
+ # π_seq is of length T+1
+ π_seq = μ_seq + C @ Eπ_seq
+
+ D = np.eye(T+1, T+1) - np.eye(T+1, T+1, k=-1) # D is the coefficient matrix in Equation (14.8)
+ m0_seq = np.append(m0, np.zeros(T))
+
+ # m_seq is of length T+2
+ m_seq = np.linalg.solve(D, μ_seq + m0_seq)
+ m_seq = np.append(m0, m_seq)
+
+ # p_seq is of length T+2
+ p_seq = m_seq + α * Eπ_seq
+
+ return π_seq, Eπ_seq, m_seq, p_seq
+```
+
++++ {"user_expressions": []}
+
+```{code-cell} ipython3
+def solve_and_plot(model, μ_seq):
+
+ π_seq, Eπ_seq, m_seq, p_seq = solve_cagan_adaptive(model, μ_seq)
+
+ T_seq = range(model.T+2)
+
+ fig, ax = plt.subplots(5, 1, figsize=[5, 12], dpi=200)
+ ax[0].plot(T_seq[:-1], μ_seq)
+ ax[1].plot(T_seq[:-1], π_seq, label=r'$\pi_t$')
+ ax[1].plot(T_seq, Eπ_seq, label=r'$\pi^{*}_{t}$')
+ ax[2].plot(T_seq, m_seq - p_seq)
+ ax[3].plot(T_seq, m_seq)
+ ax[4].plot(T_seq, p_seq)
+
+ y_labs = [r'$\mu$', r'$\pi$', r'$m - p$', r'$m$', r'$p$']
+ subplot_title = [r'Money supply growth', r'Inflation', r'Real balances', r'Money supply', r'Price level']
+
+ for i in range(5):
+ ax[i].set_xlabel(r'$t$')
+ ax[i].set_ylabel(y_labs[i])
+ ax[i].set_title(subplot_title[i])
+
+ ax[1].legend()
+ plt.tight_layout()
+ plt.show()
+
+ return π_seq, Eπ_seq, m_seq, p_seq
+```
+
++++ {"user_expressions": []}
+
+
+
+## Technical condition for stability
+
+In constructing our examples, we shall assume that $(\lambda, \alpha)$ satisfy
+
+$$
+\Bigl| \frac{\lambda-\alpha(1-\lambda)}{1-\alpha(1-\lambda)} \Bigr| < 1
+$$ (eq:suffcond)
+
+The source of this condition is the following string of deductions:
+
+$$
+\begin{aligned}
+\pi_{t}&=\mu_{t}+\alpha\pi_{t+1}^{*}-\alpha\pi_{t}^{*}\\\pi_{t+1}^{*}&=\lambda\pi_{t}^{*}+(1-\lambda)\pi_{t}\\\pi_{t}&=\frac{\mu_{t}}{1-\alpha(1-\lambda)}-\frac{\alpha(1-\lambda)}{1-\alpha(1-\lambda)}\pi_{t}^{*}\\\implies\pi_{t}^{*}&=\frac{1}{\alpha(1-\lambda)}\mu_{t}-\frac{1-\alpha(1-\lambda)}{\alpha(1-\lambda)}\pi_{t}\\\pi_{t+1}&=\frac{\mu_{t+1}}{1-\alpha(1-\lambda)}-\frac{\alpha(1-\lambda)}{1-\alpha(1-\lambda)}\left(\lambda\pi_{t}^{*}+(1-\lambda)\pi_{t}\right)\\&=\frac{\mu_{t+1}}{1-\alpha(1-\lambda)}-\frac{\lambda}{1-\alpha(1-\lambda)}\mu_{t}+\frac{\lambda-\alpha(1-\lambda)}{1-\alpha(1-\lambda)}\pi_{t}
+\end{aligned}
+$$
+
+By assuring that the coefficient on $\pi_t$ is less than one in absolute value, condition {eq}`eq:suffcond` assures stability of the dynamics of $\{\pi_t\}$ described by the last line of our string of deductions.
+
+The reader is free to study outcomes in examples that violate condition {eq}`eq:suffcond`.
+
+```{code-cell} ipython3
+print(np.abs((md.λ - md.α*(1-md.λ))/(1 - md.α*(1-md.λ))))
+```
+
+## Experiments
+
+Now we'll turn to some experiments.
+
+### Experiment 1
+
+We'll study a situation in which the rate of growth of the money supply is $\mu_0$
+from $t=0$ to $t= T_1$ and then permanently falls to $\mu^*$ at $t=T_1$.
+
+Thus, let $T_1 \in (0, T)$.
+
+So where $\mu_0 > \mu^*$, we assume that
+
+$$
+\mu_{t} = \begin{cases}
+ \mu_0 , & t = 0, \ldots, T_1 -1 \\
+ \mu^* , & t \geq T_1
+ \end{cases}
+$$
+
+Notice that we studied exactly this experiment in a rational expectations version of the model in {doc}`cagan_ree`.
+
+So by comparing outcomes across the two lectures, we can learn about consequences of assuming adaptive expectations, as we do here, instead of rational expectations as we assumed in that other lecture.
+
+```{code-cell} ipython3
+# Parameters for the experiment 1
+T1 = 60
+μ0 = 0.5
+μ_star = 0
+
+μ_seq_1 = np.append(μ0*np.ones(T1), μ_star*np.ones(md.T+1-T1))
+
+# solve and plot
+π_seq_1, Eπ_seq_1, m_seq_1, p_seq_1 = solve_and_plot(md, μ_seq_1)
+```
+
+We invite the reader to compare outcomes with those under rational expectations studied in {doc}`cagan_ree`.
+
+Please note how the actual inflation rate $\pi_t$ "overshoots" its ultimate steady-state value at the time of the sudden reduction in the rate of growth of the money supply at time $T_1$.
+
+We invite you to explain to yourself the source of this overshooting and why it does not occur in the rational expectations version of the model.
+
+### Experiment 2
+
+Now we'll do a different experiment, namely, a gradual stabilization in which the rate of growth of the money supply smoothly
+decline from a high value to a persistently low value.
+
+While price level inflation eventually falls, it falls more slowly than the driving force that ultimately causes it to fall, namely, the falling rate of growth of the money supply.
+
+The sluggish fall in inflation is explained by how anticipated inflation $\pi_t^*$ persistently exceeds actual inflation $\pi_t$ during the transition from a high inflation to a low inflation situation.
+
+```{code-cell} ipython3
+# parameters
+ϕ = 0.9
+μ_seq_2 = np.array([ϕ**t * μ0 + (1-ϕ**t)*μ_star for t in range(md.T)])
+μ_seq_2 = np.append(μ_seq_2, μ_star)
+
+
+# solve and plot
+π_seq_2, Eπ_seq_2, m_seq_2, p_seq_2 = solve_and_plot(md, μ_seq_2)
+```
diff --git a/book/_build/html/_sources/cagan_ree.ipynb b/book/_build/html/_sources/cagan_ree.ipynb
new file mode 100644
index 0000000..de74277
--- /dev/null
+++ b/book/_build/html/_sources/cagan_ree.ipynb
@@ -0,0 +1,799 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "e435e52c",
+ "metadata": {},
+ "source": [
+ "# A Monetarist Theory of Price Levels\n",
+ "\n",
+ "## Overview\n",
+ "\n",
+ "\n",
+ "We'll use linear algebra first to explain and then do some experiments with a \"monetarist theory of price levels\".\n",
+ "\n",
+ "Economists call it a \"monetary\" or \"monetarist\" theory of price levels because effects on price levels occur via a central bank's decisions to print money supply. \n",
+ "\n",
+ " * a goverment's fiscal policies determine whether its _expenditures_ exceed its _tax collections_\n",
+ " * if its expenditures exceed its tax collections, the government can instruct the central bank to cover the difference by _printing money_\n",
+ " * that leads to effects on the price level as price level path adjusts to equate the supply of money to the demand for money\n",
+ "\n",
+ "Such a theory of price levels was described by Thomas Sargent and Neil Wallace in chapter 5 of \n",
+ "{cite}`sargent2013rational`, which reprints a 1981 Federal Reserve Bank of Minneapolis article entitled \"Unpleasant Monetarist Arithmetic\". \n",
+ "\n",
+ "Sometimes this theory is also called a \"fiscal theory of price levels\" to emphasize the importance of fiscal deficits in shaping changes in the money supply. \n",
+ "\n",
+ "The theory has been extended, criticized, and applied by John Cochrane {cite}`cochrane2023fiscal`.\n",
+ "\n",
+ "In another lecture {doc}`price level histories `, we described some European hyperinflations that occurred in the wake of World War I.\n",
+ "\n",
+ "Elemental forces at work in the fiscal theory of the price level help to understand those episodes.\n",
+ "\n",
+ "\n",
+ "According to this theory, when the government persistently spends more than it collects in taxes and prints money to finance the shortfall (the \"shortfall\" is called the \"government deficit\"), it puts upward pressure on the price level and generates\n",
+ "persistent inflation.\n",
+ "\n",
+ "The \"monetarist\" or \"fiscal theory of price levels\" asserts that \n",
+ "\n",
+ "* to _start_ a persistent inflation the government begins persistently to run a money-financed government deficit\n",
+ "\n",
+ "* to _stop_ a persistent inflation the government stops persistently running a money-financed government deficit\n",
+ "\n",
+ "The model in this lecture is a \"rational expectations\" (or \"perfect foresight\") version of a model that Philip Cagan {cite}`Cagan` used to study the monetary dynamics of hyperinflations. \n",
+ "\n",
+ "While Cagan didn't use that \"rational expectations\" version of the model, Thomas Sargent {cite}`sargent1982ends` did when he studied the Ends of Four Big Inflations in Europe after World War I.\n",
+ "\n",
+ "* this lecture {doc}`fiscal theory of the price level with adaptive expectations ` describes a version of the model that does not impose \"rational expectations\" but instead uses \n",
+ " what Cagan and his teacher Milton Friedman called \"adaptive expectations\"\n",
+ "\n",
+ " * a reader of both lectures will notice that the algebra is less complicated in the present rational expectations version of the model\n",
+ " * the difference in algebra complications can be traced to the following source: the adaptive expectations version of the model has more endogenous variables and more free parameters \n",
+ "\n",
+ "Some of our quantitative experiments with the rational expectations version of the model are designed to illustrate how the fiscal theory explains the abrupt end of those big inflations.\n",
+ "\n",
+ "In those experiments, we'll encounter an instance of a \"velocity dividend\" that has sometimes accompanied successful inflation stabilization programs. \n",
+ "\n",
+ "To facilitate using linear matrix algebra as our main mathematical tool, we'll use a finite horizon version of the model.\n",
+ "\n",
+ "As in the {doc}`present values ` and {doc}`consumption smoothing` lectures, our mathematical tools are matrix multiplication and matrix inversion.\n",
+ "\n",
+ "\n",
+ "## Structure of the model\n",
+ "\n",
+ "\n",
+ "The model consists of\n",
+ "\n",
+ "* a function that expresses the demand for real balances of government printed money as an inverse function of the public's expected rate of inflation\n",
+ "\n",
+ "* an exogenous sequence of rates of growth of the money supply. The money supply grows because the government prints it to pay for goods and services\n",
+ "\n",
+ "* an equilibrium condition that equates the demand for money to the supply\n",
+ "\n",
+ "* a \"perfect foresight\" assumption that the public's expected rate of inflation equals the actual rate of inflation.\n",
+ " \n",
+ "To represent the model formally, let \n",
+ "\n",
+ "* $ m_t $ be the log of the supply of nominal money balances;\n",
+ "* $\\mu_t = m_{t+1} - m_t $ be the net rate of growth of nominal balances;\n",
+ "* $p_t $ be the log of the price level;\n",
+ "* $\\pi_t = p_{t+1} - p_t $ be the net rate of inflation between $t$ and $ t+1$;\n",
+ "* $\\pi_t^*$ be the public's expected rate of inflation between $t$ and $t+1$;\n",
+ "* $T$ the horizon -- i.e., the last period for which the model will determine $p_t$\n",
+ "* $\\pi_{T+1}^*$ the terminal rate of inflation between times $T$ and $T+1$.\n",
+ "\n",
+ "The demand for real balances $\\exp\\left(m_t^d - p_t\\right)$ is governed by the following version of the Cagan demand function\n",
+ " \n",
+ "$$ \n",
+ "m_t^d - p_t = -\\alpha \\pi_t^* \\: , \\: \\alpha > 0 ; \\quad t = 0, 1, \\ldots, T .\n",
+ "$$ (eq:caganmd)\n",
+ "\n",
+ "This equation asserts that the demand for real balances\n",
+ "is inversely related to the public's expected rate of inflation with sensitivity $\\alpha$.\n",
+ "\n",
+ "People somehow acquire **perfect foresight** by their having solved a forecasting\n",
+ "problem.\n",
+ "\n",
+ "This lets us set\n",
+ "\n",
+ "$$ \n",
+ "\\pi_t^* = \\pi_t , % \\forall t \n",
+ "$$ (eq:ree)\n",
+ "\n",
+ "while equating demand for money to supply lets us set $m_t^d = m_t$ for all $t \\geq 0$. \n",
+ "\n",
+ "The preceding equations then imply\n",
+ "\n",
+ "$$\n",
+ "m_t - p_t = -\\alpha(p_{t+1} - p_t)\n",
+ "$$ (eq:cagan)\n",
+ "\n",
+ "To fill in details about what it means for private agents\n",
+ "to have perfect foresight, we subtract equation {eq}`eq:cagan` at time $ t $ from the same equation at $ t+1$ to get\n",
+ "\n",
+ "$$\n",
+ "\\mu_t - \\pi_t = -\\alpha \\pi_{t+1} + \\alpha \\pi_t ,\n",
+ "$$\n",
+ "\n",
+ "which we rewrite as a forward-looking first-order linear difference\n",
+ "equation in $\\pi_s$ with $\\mu_s$ as a \"forcing variable\":\n",
+ "\n",
+ "$$\n",
+ "\\pi_t = \\frac{\\alpha}{1+\\alpha} \\pi_{t+1} + \\frac{1}{1+\\alpha} \\mu_t , \\quad t= 0, 1, \\ldots , T \n",
+ "$$\n",
+ "\n",
+ "where $ 0< \\frac{\\alpha}{1+\\alpha} <1 $.\n",
+ "\n",
+ "Setting $\\delta =\\frac{\\alpha}{1+\\alpha}$, let's us represent the preceding equation as\n",
+ "\n",
+ "$$\n",
+ "\\pi_t = \\delta \\pi_{t+1} + (1-\\delta) \\mu_t , \\quad t =0, 1, \\ldots, T\n",
+ "$$\n",
+ "\n",
+ "Write this system of $T+1$ equations as the single matrix equation\n",
+ "\n",
+ "$$\n",
+ "\\begin{bmatrix} 1 & -\\delta & 0 & 0 & \\cdots & 0 & 0 \\cr\n",
+ " 0 & 1 & -\\delta & 0 & \\cdots & 0 & 0 \\cr\n",
+ " 0 & 0 & 1 & -\\delta & \\cdots & 0 & 0 \\cr\n",
+ " \\vdots & \\vdots & \\vdots & \\vdots & \\vdots & -\\delta & 0 \\cr\n",
+ " 0 & 0 & 0 & 0 & \\cdots & 1 & -\\delta \\cr\n",
+ " 0 & 0 & 0 & 0 & \\cdots & 0 & 1 \\end{bmatrix}\n",
+ "\\begin{bmatrix} \\pi_0 \\cr \\pi_1 \\cr \\pi_2 \\cr \\vdots \\cr \\pi_{T-1} \\cr \\pi_T \n",
+ "\\end{bmatrix} \n",
+ "= (1 - \\delta) \\begin{bmatrix} \n",
+ "\\mu_0 \\cr \\mu_1 \\cr \\mu_2 \\cr \\vdots \\cr \\mu_{T-1} \\cr \\mu_T\n",
+ "\\end{bmatrix}\n",
+ "+ \\begin{bmatrix} \n",
+ "0 \\cr 0 \\cr 0 \\cr \\vdots \\cr 0 \\cr \\delta \\pi_{T+1}^*\n",
+ "\\end{bmatrix}\n",
+ "$$ (eq:pieq)\n",
+ "\n",
+ "By multiplying both sides of equation {eq}`eq:pieq` by the inverse of the matrix on the left side, we can calculate\n",
+ "\n",
+ "$$\n",
+ "\\pi \\equiv \\begin{bmatrix} \\pi_0 \\cr \\pi_1 \\cr \\pi_2 \\cr \\vdots \\cr \\pi_{T-1} \\cr \\pi_T \n",
+ "\\end{bmatrix} \n",
+ "$$\n",
+ "\n",
+ "It turns out that\n",
+ "\n",
+ "$$\n",
+ "\\pi_t = (1-\\delta) \\sum_{s=t}^T \\delta^{s-t} \\mu_s + \\delta^{T+1-t} \\pi_{T+1}^*\n",
+ "$$ (eq:fisctheory1)\n",
+ "\n",
+ "We can represent the equations \n",
+ "\n",
+ "$$ \n",
+ "m_{t+1} = m_t + \\mu_t , \\quad t = 0, 1, \\ldots, T\n",
+ "$$\n",
+ "\n",
+ "as the matrix equation\n",
+ "\n",
+ "$$\n",
+ "\\begin{bmatrix}\n",
+ "1 & 0 & 0 & \\cdots & 0 & 0 \\cr\n",
+ "-1 & 1 & 0 & \\cdots & 0 & 0 \\cr\n",
+ "0 & -1 & 1 & \\cdots & 0 & 0 \\cr\n",
+ "\\vdots & \\vdots & \\vdots & \\vdots & 0 & 0 \\cr\n",
+ "0 & 0 & 0 & \\cdots & 1 & 0 \\cr\n",
+ "0 & 0 & 0 & \\cdots & -1 & 1 \n",
+ "\\end{bmatrix}\n",
+ "\\begin{bmatrix} \n",
+ "m_1 \\cr m_2 \\cr m_3 \\cr \\vdots \\cr m_T \\cr m_{T+1}\n",
+ "\\end{bmatrix}\n",
+ "= \\begin{bmatrix} \n",
+ "\\mu_0 \\cr \\mu_1 \\cr \\mu_2 \\cr \\vdots \\cr \\mu_{T-1} \\cr \\mu_T\n",
+ "\\end{bmatrix}\n",
+ "+ \\begin{bmatrix} \n",
+ "m_0 \\cr 0 \\cr 0 \\cr \\vdots \\cr 0 \\cr 0\n",
+ "\\end{bmatrix}\n",
+ "$$ (eq:eq101)\n",
+ "\n",
+ "Multiplying both sides of equation {eq}`eq:eq101` with the inverse of the matrix on the left will give \n",
+ "\n",
+ "$$\n",
+ "m_t = m_0 + \\sum_{s=0}^{t-1} \\mu_s, \\quad t =1, \\ldots, T+1\n",
+ "$$ (eq:mcum)\n",
+ "\n",
+ "Equation {eq}`eq:mcum` shows that the log of the money supply at $t$ equals the log of the initial money supply $m_0$\n",
+ "plus accumulation of rates of money growth between times $0$ and $T$.\n",
+ "\n",
+ "## Continuation values\n",
+ "\n",
+ "To determine the continuation inflation rate $\\pi_{T+1}^*$ we shall proceed by applying the following infinite-horizon\n",
+ "version of equation {eq}`eq:fisctheory1` at time $t = T+1$:\n",
+ "\n",
+ "$$\n",
+ "\\pi_t = (1-\\delta) \\sum_{s=t}^\\infty \\delta^{s-t} \\mu_s , \n",
+ "$$ (eq:fisctheory2)\n",
+ "\n",
+ "and by also assuming the following continuation path for $\\mu_t$ beyond $T$:\n",
+ "\n",
+ "$$\n",
+ "\\mu_{t+1} = \\gamma^* \\mu_t, \\quad t \\geq T .\n",
+ "$$\n",
+ "\n",
+ "Plugging the preceding equation into equation {eq}`eq:fisctheory2` at $t = T+1$ and rearranging we can deduce that\n",
+ "\n",
+ "$$ \n",
+ "\\pi_{T+1}^* = \\frac{1 - \\delta}{1 - \\delta \\gamma^*} \\gamma^* \\mu_T\n",
+ "$$ (eq:piterm)\n",
+ "\n",
+ "where we require that $\\vert \\gamma^* \\delta \\vert < 1$.\n",
+ "\n",
+ "Let's implement and solve this model.\n",
+ "\n",
+ "\n",
+ "As usual, we'll start by importing some Python modules."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c8a5b5e9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "from collections import namedtuple\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "39cb0268",
+ "metadata": {},
+ "source": [
+ "First, we store parameters in a `namedtuple`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "593512ee",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Create the rational expectation version of Cagan model in finite time\n",
+ "CaganREE = namedtuple(\"CaganREE\", \n",
+ " [\"m0\", # initial money supply\n",
+ " \"μ_seq\", # sequence of rate of growth\n",
+ " \"α\", # sensitivity parameter\n",
+ " \"δ\", # α/(1 + α)\n",
+ " \"π_end\" # terminal expected inflation\n",
+ " ])\n",
+ "\n",
+ "def create_cagan_model(m0=1, α=5, μ_seq=None):\n",
+ " δ = α/(1 + α)\n",
+ " π_end = μ_seq[-1] # compute terminal expected inflation\n",
+ " return CaganREE(m0, μ_seq, α, δ, π_end)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7a646e4d",
+ "metadata": {},
+ "source": [
+ "Now we can solve the model to compute $\\pi_t$, $m_t$ and $p_t$ for $t =1, \\ldots, T+1$ using the matrix equation above"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b141be4e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def solve(model, T):\n",
+ " m0, π_end, μ_seq, α, δ = (model.m0, model.π_end, \n",
+ " model.μ_seq, model.α, model.δ)\n",
+ " \n",
+ " # Create matrix representation above\n",
+ " A1 = np.eye(T+1, T+1) - δ * np.eye(T+1, T+1, k=1)\n",
+ " A2 = np.eye(T+1, T+1) - np.eye(T+1, T+1, k=-1)\n",
+ "\n",
+ " b1 = (1-δ) * μ_seq + np.concatenate([np.zeros(T), [δ * π_end]])\n",
+ " b2 = μ_seq + np.concatenate([[m0], np.zeros(T)])\n",
+ "\n",
+ " π_seq = np.linalg.solve(A1, b1)\n",
+ " m_seq = np.linalg.solve(A2, b2)\n",
+ "\n",
+ " π_seq = np.append(π_seq, π_end)\n",
+ " m_seq = np.append(m0, m_seq)\n",
+ "\n",
+ " p_seq = m_seq + α * π_seq\n",
+ "\n",
+ " return π_seq, m_seq, p_seq"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4afc6cb4",
+ "metadata": {},
+ "source": [
+ "### Some quantitative experiments\n",
+ "\n",
+ "In the experiments below, we'll use formula {eq}`eq:piterm` as our terminal condition for expected inflation.\n",
+ "\n",
+ "In devising these experiments, we'll make assumptions about $\\{\\mu_t\\}$ that are consistent with formula\n",
+ "{eq}`eq:piterm`.\n",
+ "\n",
+ "We describe several such experiments.\n",
+ "\n",
+ "In all of them, \n",
+ "\n",
+ "$$ \n",
+ "\\mu_t = \\mu^* , \\quad t \\geq T_1\n",
+ "$$\n",
+ "\n",
+ "so that, in terms of our notation and formula for $\\pi_{T+1}^*$ above, $\\gamma^* = 1$. \n",
+ "\n",
+ "#### Experiment 1: Foreseen sudden stabilization\n",
+ "\n",
+ "In this experiment, we'll study how, when $\\alpha >0$, a foreseen inflation stabilization has effects on inflation that proceed it.\n",
+ "\n",
+ "We'll study a situation in which the rate of growth of the money supply is $\\mu_0$\n",
+ "from $t=0$ to $t= T_1$ and then permanently falls to $\\mu^*$ at $t=T_1$.\n",
+ "\n",
+ "Thus, let $T_1 \\in (0, T)$. \n",
+ "\n",
+ "So where $\\mu_0 > \\mu^*$, we assume that\n",
+ "\n",
+ "$$\n",
+ "\\mu_{t+1} = \\begin{cases}\n",
+ " \\mu_0 , & t = 0, \\ldots, T_1 -1 \\\\\n",
+ " \\mu^* , & t \\geq T_1\n",
+ " \\end{cases}\n",
+ "$$\n",
+ "\n",
+ "We'll start by executing a version of our \"experiment 1\" in which the government implements a _foreseen_ sudden permanent reduction in the rate of money creation at time $T_1$. \n",
+ "\n",
+ "Let's experiment with the following parameters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "02813994",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "T1 = 60\n",
+ "μ0 = 0.5\n",
+ "μ_star = 0\n",
+ "T = 80\n",
+ "\n",
+ "μ_seq_1 = np.append(μ0*np.ones(T1+1), μ_star*np.ones(T-T1))\n",
+ "\n",
+ "cm = create_cagan_model(μ_seq=μ_seq_1)\n",
+ "\n",
+ "# solve the model\n",
+ "π_seq_1, m_seq_1, p_seq_1 = solve(cm, T)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f69c9e6a",
+ "metadata": {},
+ "source": [
+ "Now we use the following function to plot the result"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "20caab8e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plot_sequences(sequences, labels):\n",
+ " fig, axs = plt.subplots(len(sequences), 1, figsize=(5, 12), dpi=200)\n",
+ " for ax, seq, label in zip(axs, sequences, labels):\n",
+ " ax.plot(range(len(seq)), seq, label=label)\n",
+ " ax.set_ylabel(label)\n",
+ " ax.set_xlabel('$t$')\n",
+ " ax.legend()\n",
+ " plt.tight_layout()\n",
+ " plt.show()\n",
+ "\n",
+ "sequences = (μ_seq_1, π_seq_1, m_seq_1 - p_seq_1, m_seq_1, p_seq_1)\n",
+ "plot_sequences(sequences, (r'$\\mu$', r'$\\pi$', r'$m - p$', r'$m$', r'$p$'))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e6d6d7ae",
+ "metadata": {},
+ "source": [
+ "The plot of the money growth rate $\\mu_t$ in the top level panel portrays\n",
+ "a sudden reduction from $.5$ to $0$ at time $T_1 = 60$. \n",
+ "\n",
+ "This brings about a gradual reduction of the inflation rate $\\pi_t$ that precedes the\n",
+ "money supply growth rate reduction at time $T_1$.\n",
+ "\n",
+ "Notice how the inflation rate declines smoothly (i.e., continuously) to $0$ at $T_1$ -- \n",
+ "unlike the money growth rate, it does not suddenly \"jump\" downward at $T_1$.\n",
+ "\n",
+ "This is because the reduction in $\\mu$ at $T_1$ has been foreseen from the start. \n",
+ "\n",
+ "While the log money supply portrayed in the bottom panel has a kink at $T_1$, the log price level does not -- it is \"smooth\" -- once again a consequence of the fact that the\n",
+ "reduction in $\\mu$ has been foreseen.\n",
+ "\n",
+ "To set the stage for our next experiment, we want to study the determinants of the price level a little more.\n",
+ "\n",
+ "\n",
+ "### The log price level\n",
+ "\n",
+ "We can use equations {eq}`eq:caganmd` and {eq}`eq:ree`\n",
+ "to discover that the log of the price level satisfies\n",
+ "\n",
+ "$$\n",
+ "p_t = m_t + \\alpha \\pi_t\n",
+ "$$ (eq:pformula2)\n",
+ "\n",
+ "or, by using equation {eq}`eq:fisctheory1`,\n",
+ "\n",
+ "$$ \n",
+ "p_t = m_t + \\alpha \\left[ (1-\\delta) \\sum_{s=t}^T \\delta^{s-t} \\mu_s + \\delta^{T+1-t} \\pi_{T+1}^* \\right] \n",
+ "$$ (eq:pfiscaltheory2)\n",
+ "\n",
+ "In our next experiment, we'll study a \"surprise\" permanent change in the money growth that beforehand \n",
+ "was completely unanticipated. \n",
+ "\n",
+ "At time $T_1$ when the \"surprise\" money growth rate change occurs, to satisfy\n",
+ "equation {eq}`eq:pformula2`, the log of real balances jumps \n",
+ "_upward_ as $\\pi_t$ jumps _downward_.\n",
+ "\n",
+ "But in order for $m_t - p_t$ to jump, which variable jumps, $m_{T_1}$ or $p_{T_1}$?\n",
+ "\n",
+ "We'll study that interesting question next.\n",
+ "\n",
+ "### What jumps?\n",
+ "\n",
+ "What jumps at $T_1$?\n",
+ "\n",
+ "Is it $p_{T_1}$ or $m_{T_1}$?\n",
+ "\n",
+ "If we insist that the money supply $m_{T_1}$ is locked at its value $m_{T_1}^1$ inherited from the past, then formula {eq}`eq:pformula2` implies that the price level jumps downward at time $T_1$, to coincide with the downward jump in \n",
+ "$\\pi_{T_1}$ \n",
+ "\n",
+ "An alternative assumption about the money supply level is that as part of the \"inflation stabilization\",\n",
+ "the government resets $m_{T_1}$ according to\n",
+ "\n",
+ "$$\n",
+ "m_{T_1}^2 - m_{T_1}^1 = \\alpha (\\pi_{T_1}^1 - \\pi_{T_1}^2),\n",
+ "$$ (eq:eqnmoneyjump)\n",
+ "\n",
+ "which describes how the government could reset the money supply at $T_1$ in response to the jump in expected inflation associated with monetary stabilization. \n",
+ "\n",
+ "Doing this would let the price level be continuous at $T_1$.\n",
+ "\n",
+ "By letting money jump according to equation {eq}`eq:eqnmoneyjump` the monetary authority prevents the price level from _falling_ at the moment that the unanticipated stabilization arrives.\n",
+ "\n",
+ "In various research papers about stabilizations of high inflations, the jump in the money supply described by equation {eq}`eq:eqnmoneyjump` has been called\n",
+ "\"the velocity dividend\" that a government reaps from implementing a regime change that sustains a permanently lower inflation rate.\n",
+ "\n",
+ "#### Technical details about whether $p$ or $m$ jumps at $T_1$\n",
+ "\n",
+ "We have noted that with a constant expected forward sequence $\\mu_s = \\bar \\mu$ for $s\\geq t$, $\\pi_{t} =\\bar{\\mu}$.\n",
+ "\n",
+ "A consequence is that at $T_1$, either $m$ or $p$ must \"jump\" at $T_1$.\n",
+ "\n",
+ "We'll study both cases. \n",
+ "\n",
+ "#### $m_{T_{1}}$ does not jump.\n",
+ "\n",
+ "$$\n",
+ "\\begin{aligned}\n",
+ "m_{T_{1}}&=m_{T_{1}-1}+\\mu_{0}\\\\\\pi_{T_{1}}&=\\mu^{*}\\\\p_{T_{1}}&=m_{T_{1}}+\\alpha\\pi_{T_{1}}\n",
+ "\\end{aligned}\n",
+ "$$\n",
+ "\n",
+ "Simply glue the sequences $t\\leq T_1$ and $t > T_1$.\n",
+ "\n",
+ "#### $m_{T_{1}}$ jumps.\n",
+ "\n",
+ "We reset $m_{T_{1}}$ so that $p_{T_{1}}=\\left(m_{T_{1}-1}+\\mu_{0}\\right)+\\alpha\\mu_{0}$, with $\\pi_{T_{1}}=\\mu^{*}$.\n",
+ "\n",
+ "Then, \n",
+ "\n",
+ "$$ \n",
+ "m_{T_{1}}=p_{T_{1}}-\\alpha\\pi_{T_{1}}=\\left(m_{T_{1}-1}+\\mu_{0}\\right)+\\alpha\\left(\\mu_{0}-\\mu^{*}\\right) \n",
+ "$$\n",
+ "\n",
+ "We then compute for the remaining $T-T_{1}$ periods with $\\mu_{s}=\\mu^{*},\\forall s\\geq T_{1}$ and the initial condition $m_{T_{1}}$ from above.\n",
+ "\n",
+ "We are now technically equipped to discuss our next experiment.\n",
+ "\n",
+ "#### Experiment 2: an unforeseen sudden stabilization\n",
+ "\n",
+ "This experiment deviates a little bit from a pure version of our \"perfect foresight\"\n",
+ "assumption by assuming that a sudden permanent reduction in $\\mu_t$ like that\n",
+ "analyzed in experiment 1 is completely unanticipated. \n",
+ "\n",
+ "Such a completely unanticipated shock is popularly known as an \"MIT shock\".\n",
+ "\n",
+ "The mental experiment involves switching at time $T_1$ from an initial \"continuation path\" for $\\{\\mu_t, \\pi_t\\} $ to another path that involves a permanently lower inflation rate. \n",
+ "\n",
+ "**Initial Path:** $\\mu_t = \\mu_0$ for all $t \\geq 0$. So this path is for $\\{\\mu_t\\}_{t=0}^\\infty$; the associated \n",
+ "path for $\\pi_t$ has $\\pi_t = \\mu_0$. \n",
+ "\n",
+ "**Revised Continuation Path** Where $ \\mu_0 > \\mu^*$, we construct a continuation path $\\{\\mu_s\\}_{s=T_1}^\\infty$\n",
+ "by setting $\\mu_s = \\mu^*$ for all $s \\geq T_1$. The perfect foresight continuation path for \n",
+ "$\\pi$ is $\\pi_s = \\mu^*$ \n",
+ "\n",
+ "To capture a \"completely unanticipated permanent shock to the $\\{\\mu_t\\}$ process at time $T_1$, we simply glue the $\\mu_t, \\pi_t$\n",
+ "that emerges under path 2 for $t \\geq T_1$ to the $\\mu_t, \\pi_t$ path that had emerged under path 1 for $ t=0, \\ldots,\n",
+ "T_1 -1$.\n",
+ "\n",
+ "We can do the MIT shock calculations mostly by hand. \n",
+ "\n",
+ "Thus, for path 1, $\\pi_t = \\mu_0 $ for all $t \\in [0, T_1-1]$, while for path 2,\n",
+ "$\\mu_s = \\mu^*$ for all $s \\geq T_1$. \n",
+ "\n",
+ "We now move on to experiment 2, our \"MIT shock\", completely unforeseen \n",
+ "sudden stabilization.\n",
+ "\n",
+ "We set this up so that the $\\{\\mu_t\\}$ sequences that describe the sudden stabilization\n",
+ "are identical to those for experiment 1, the foreseen sudden stabilization.\n",
+ "\n",
+ "The following code does the calculations and plots outcomes."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7e89c727",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# path 1\n",
+ "μ_seq_2_path1 = μ0 * np.ones(T+1)\n",
+ "\n",
+ "cm1 = create_cagan_model(μ_seq=μ_seq_2_path1)\n",
+ "π_seq_2_path1, m_seq_2_path1, p_seq_2_path1 = solve(cm1, T)\n",
+ "\n",
+ "# continuation path\n",
+ "μ_seq_2_cont = μ_star * np.ones(T-T1)\n",
+ "\n",
+ "cm2 = create_cagan_model(m0=m_seq_2_path1[T1+1], \n",
+ " μ_seq=μ_seq_2_cont)\n",
+ "π_seq_2_cont, m_seq_2_cont1, p_seq_2_cont1 = solve(cm2, T-1-T1)\n",
+ "\n",
+ "\n",
+ "# regime 1 - simply glue π_seq, μ_seq\n",
+ "μ_seq_2 = np.concatenate((μ_seq_2_path1[:T1+1],\n",
+ " μ_seq_2_cont))\n",
+ "π_seq_2 = np.concatenate((π_seq_2_path1[:T1+1], \n",
+ " π_seq_2_cont))\n",
+ "m_seq_2_regime1 = np.concatenate((m_seq_2_path1[:T1+1], \n",
+ " m_seq_2_cont1))\n",
+ "p_seq_2_regime1 = np.concatenate((p_seq_2_path1[:T1+1], \n",
+ " p_seq_2_cont1))\n",
+ "\n",
+ "# regime 2 - reset m_T1\n",
+ "m_T1 = (m_seq_2_path1[T1] + μ0) + cm2.α*(μ0 - μ_star)\n",
+ "\n",
+ "cm3 = create_cagan_model(m0=m_T1, μ_seq=μ_seq_2_cont)\n",
+ "π_seq_2_cont2, m_seq_2_cont2, p_seq_2_cont2 = solve(cm3, T-1-T1)\n",
+ "\n",
+ "m_seq_2_regime2 = np.concatenate((m_seq_2_path1[:T1+1], \n",
+ " m_seq_2_cont2))\n",
+ "p_seq_2_regime2 = np.concatenate((p_seq_2_path1[:T1+1],\n",
+ " p_seq_2_cont2))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b1221aa4",
+ "metadata": {
+ "tags": [
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "T_seq = range(T+2)\n",
+ "\n",
+ "# plot both regimes\n",
+ "fig, ax = plt.subplots(5, 1, figsize=(5, 12), dpi=200)\n",
+ "\n",
+ "# Configuration for each subplot\n",
+ "plot_configs = [\n",
+ " {'data': [(T_seq[:-1], μ_seq_2)], 'ylabel': r'$\\mu$'},\n",
+ " {'data': [(T_seq, π_seq_2)], 'ylabel': r'$\\pi$'},\n",
+ " {'data': [(T_seq, m_seq_2_regime1 - p_seq_2_regime1)], \n",
+ " 'ylabel': r'$m - p$'},\n",
+ " {'data': [(T_seq, m_seq_2_regime1, 'Smooth $m_{T_1}$'), \n",
+ " (T_seq, m_seq_2_regime2, 'Jumpy $m_{T_1}$')], \n",
+ " 'ylabel': r'$m$'},\n",
+ " {'data': [(T_seq, p_seq_2_regime1, 'Smooth $p_{T_1}$'), \n",
+ " (T_seq, p_seq_2_regime2, 'Jumpy $p_{T_1}$')], \n",
+ " 'ylabel': r'$p$'}\n",
+ "]\n",
+ "\n",
+ "def experiment_plot(plot_configs, ax):\n",
+ " # Loop through each subplot configuration\n",
+ " for axi, config in zip(ax, plot_configs):\n",
+ " for data in config['data']:\n",
+ " if len(data) == 3: # Plot with label for legend\n",
+ " axi.plot(data[0], data[1], label=data[2])\n",
+ " axi.legend()\n",
+ " else: # Plot without label\n",
+ " axi.plot(data[0], data[1])\n",
+ " axi.set_ylabel(config['ylabel'])\n",
+ " axi.set_xlabel(r'$t$')\n",
+ " plt.tight_layout()\n",
+ " plt.show()\n",
+ " \n",
+ "experiment_plot(plot_configs, ax)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "cdca3cb8",
+ "metadata": {},
+ "source": [
+ "We invite you to compare these graphs with corresponding ones for the foreseen stabilization analyzed in experiment 1 above.\n",
+ "\n",
+ "Note how the inflation graph in the second panel is now identical to the \n",
+ "money growth graph in the top panel, and how now the log of real balances portrayed in the third panel jumps upward at time $T_1$.\n",
+ "\n",
+ "The bottom two panels plot $m$ and $p$ under two possible ways that $m_{T_1}$ might adjust\n",
+ "as required by the upward jump in $m - p$ at $T_1$. \n",
+ "\n",
+ "* the orange line lets $m_{T_1}$ jump upward in order to make sure that the log price level $p_{T_1}$ does not fall.\n",
+ "\n",
+ "* the blue line lets $p_{T_1}$ fall while stopping the money supply from jumping.\n",
+ " \n",
+ "Here is a way to interpret what the government is doing when the orange line policy is in place.\n",
+ "\n",
+ "The government prints money to finance expenditure with the \"velocity dividend\" that it reaps from the increased demand for real balances brought about by the permanent decrease in the rate of growth of the money supply.\n",
+ "\n",
+ "The next code generates a multi-panel graph that includes outcomes of both experiments 1 and 2.\n",
+ "\n",
+ "That allows us to assess how important it is to understand whether the sudden permanent drop in $\\mu_t$ at $t=T_1$ is fully unanticipated, as in experiment 1, or completely\n",
+ "unanticipated, as in experiment 2."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "90036eb7",
+ "metadata": {
+ "tags": [
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "# compare foreseen vs unforeseen shock\n",
+ "fig, ax = plt.subplots(5, figsize=(5, 12), dpi=200)\n",
+ "\n",
+ "plot_configs = [\n",
+ " {'data': [(T_seq[:-1], μ_seq_2)], 'ylabel': r'$\\mu$'},\n",
+ " {'data': [(T_seq, π_seq_2, 'Unforeseen'), \n",
+ " (T_seq, π_seq_1, 'Foreseen')], 'ylabel': r'$p$'},\n",
+ " {'data': [(T_seq, m_seq_2_regime1 - p_seq_2_regime1, 'Unforeseen'), \n",
+ " (T_seq, m_seq_1 - p_seq_1, 'Foreseen')], 'ylabel': r'$m - p$'},\n",
+ " {'data': [(T_seq, m_seq_2_regime1, 'Unforeseen (Smooth $m_{T_1}$)'), \n",
+ " (T_seq, m_seq_2_regime2, 'Unforeseen ($m_{T_1}$ jumps)'),\n",
+ " (T_seq, m_seq_1, 'Foreseen')], 'ylabel': r'$m$'}, \n",
+ " {'data': [(T_seq, p_seq_2_regime1, 'Unforeseen (Smooth $m_{T_1}$)'), \n",
+ " (T_seq, p_seq_2_regime2, 'Unforeseen ($m_{T_1}$ jumps)'),\n",
+ " (T_seq, p_seq_1, 'Foreseen')], 'ylabel': r'$p$'} \n",
+ "]\n",
+ "\n",
+ "experiment_plot(plot_configs, ax)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c5fdd115",
+ "metadata": {},
+ "source": [
+ "It is instructive to compare the preceding graphs with graphs of log price levels and inflation rates for data from four big inflations described in\n",
+ "{doc}`this lecture `.\n",
+ "\n",
+ "In particular, in the above graphs, notice how a gradual fall in inflation precedes the \"sudden stop\" when it has been anticipated long beforehand, but how\n",
+ "inflation instead falls abruptly when the permanent drop in money supply growth is unanticipated.\n",
+ "\n",
+ "It seems to the author team at quantecon that the drops in inflation near the ends of the four hyperinflations described in {doc}`this lecture `\n",
+ "more closely resemble outcomes from the experiment 2 \"unforeseen stabilization\". \n",
+ "\n",
+ "(It is fair to say that the preceding informal pattern recognition exercise should be supplemented with a more formal structural statistical analysis.)\n",
+ "\n",
+ "#### Experiment 3\n",
+ "\n",
+ "**Foreseen gradual stabilization**\n",
+ "\n",
+ "Instead of a foreseen sudden stabilization of the type studied with experiment 1,\n",
+ "it is also interesting to study the consequences of a foreseen gradual stabilization.\n",
+ "\n",
+ "Thus, suppose that $\\phi \\in (0,1)$, that $\\mu_0 > \\mu^*$, and that for $t = 0, \\ldots, T-1$\n",
+ "\n",
+ "$$\n",
+ "\\mu_t = \\phi^t \\mu_0 + (1 - \\phi^t) \\mu^* .\n",
+ "$$ \n",
+ "\n",
+ "Next we perform an experiment in which there is a perfectly foreseen _gradual_ decrease in the rate of growth of the money supply.\n",
+ "\n",
+ "The following code does the calculations and plots the results."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "13e2baf1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# parameters\n",
+ "ϕ = 0.9\n",
+ "μ_seq_stab = np.array([ϕ**t * μ0 + (1-ϕ**t)*μ_star for t in range(T)])\n",
+ "μ_seq_stab = np.append(μ_seq_stab, μ_star)\n",
+ "\n",
+ "cm4 = create_cagan_model(μ_seq=μ_seq_stab)\n",
+ "\n",
+ "π_seq_4, m_seq_4, p_seq_4 = solve(cm4, T)\n",
+ "\n",
+ "sequences = (μ_seq_stab, π_seq_4, \n",
+ " m_seq_4 - p_seq_4, m_seq_4, p_seq_4)\n",
+ "plot_sequences(sequences, (r'$\\mu$', r'$\\pi$', \n",
+ " r'$m - p$', r'$m$', r'$p$'))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8b6ee97f",
+ "metadata": {},
+ "source": [
+ "## Sequel\n",
+ "\n",
+ "Another lecture {doc}`monetarist theory of price levels with adaptive expectations ` describes an \"adaptive expectations\" version of Cagan's model.\n",
+ "\n",
+ "The dynamics become more complicated and so does the algebra.\n",
+ "\n",
+ "Nowadays, the \"rational expectations\" version of the model is more popular among central bankers and economists advising them."
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.16.1"
+ }
+ },
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "source_map": [
+ 12,
+ 235,
+ 239,
+ 243,
+ 257,
+ 261,
+ 282,
+ 323,
+ 335,
+ 339,
+ 352,
+ 488,
+ 525,
+ 562,
+ 585,
+ 606,
+ 636,
+ 650
+ ]
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/cagan_ree.md b/book/_build/html/_sources/cagan_ree.md
new file mode 100644
index 0000000..f0274b5
--- /dev/null
+++ b/book/_build/html/_sources/cagan_ree.md
@@ -0,0 +1,658 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.16.1
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+# A Monetarist Theory of Price Levels
+
+## Overview
+
+
+We'll use linear algebra first to explain and then do some experiments with a "monetarist theory of price levels".
+
+Economists call it a "monetary" or "monetarist" theory of price levels because effects on price levels occur via a central bank's decisions to print money supply.
+
+ * a goverment's fiscal policies determine whether its _expenditures_ exceed its _tax collections_
+ * if its expenditures exceed its tax collections, the government can instruct the central bank to cover the difference by _printing money_
+ * that leads to effects on the price level as price level path adjusts to equate the supply of money to the demand for money
+
+Such a theory of price levels was described by Thomas Sargent and Neil Wallace in chapter 5 of
+{cite}`sargent2013rational`, which reprints a 1981 Federal Reserve Bank of Minneapolis article entitled "Unpleasant Monetarist Arithmetic".
+
+Sometimes this theory is also called a "fiscal theory of price levels" to emphasize the importance of fiscal deficits in shaping changes in the money supply.
+
+The theory has been extended, criticized, and applied by John Cochrane {cite}`cochrane2023fiscal`.
+
+In another lecture {doc}`price level histories `, we described some European hyperinflations that occurred in the wake of World War I.
+
+Elemental forces at work in the fiscal theory of the price level help to understand those episodes.
+
+
+According to this theory, when the government persistently spends more than it collects in taxes and prints money to finance the shortfall (the "shortfall" is called the "government deficit"), it puts upward pressure on the price level and generates
+persistent inflation.
+
+The "monetarist" or "fiscal theory of price levels" asserts that
+
+* to _start_ a persistent inflation the government begins persistently to run a money-financed government deficit
+
+* to _stop_ a persistent inflation the government stops persistently running a money-financed government deficit
+
+The model in this lecture is a "rational expectations" (or "perfect foresight") version of a model that Philip Cagan {cite}`Cagan` used to study the monetary dynamics of hyperinflations.
+
+While Cagan didn't use that "rational expectations" version of the model, Thomas Sargent {cite}`sargent1982ends` did when he studied the Ends of Four Big Inflations in Europe after World War I.
+
+* this lecture {doc}`fiscal theory of the price level with adaptive expectations ` describes a version of the model that does not impose "rational expectations" but instead uses
+ what Cagan and his teacher Milton Friedman called "adaptive expectations"
+
+ * a reader of both lectures will notice that the algebra is less complicated in the present rational expectations version of the model
+ * the difference in algebra complications can be traced to the following source: the adaptive expectations version of the model has more endogenous variables and more free parameters
+
+Some of our quantitative experiments with the rational expectations version of the model are designed to illustrate how the fiscal theory explains the abrupt end of those big inflations.
+
+In those experiments, we'll encounter an instance of a "velocity dividend" that has sometimes accompanied successful inflation stabilization programs.
+
+To facilitate using linear matrix algebra as our main mathematical tool, we'll use a finite horizon version of the model.
+
+As in the {doc}`present values ` and {doc}`consumption smoothing` lectures, our mathematical tools are matrix multiplication and matrix inversion.
+
+
+## Structure of the model
+
+
+The model consists of
+
+* a function that expresses the demand for real balances of government printed money as an inverse function of the public's expected rate of inflation
+
+* an exogenous sequence of rates of growth of the money supply. The money supply grows because the government prints it to pay for goods and services
+
+* an equilibrium condition that equates the demand for money to the supply
+
+* a "perfect foresight" assumption that the public's expected rate of inflation equals the actual rate of inflation.
+
+To represent the model formally, let
+
+* $ m_t $ be the log of the supply of nominal money balances;
+* $\mu_t = m_{t+1} - m_t $ be the net rate of growth of nominal balances;
+* $p_t $ be the log of the price level;
+* $\pi_t = p_{t+1} - p_t $ be the net rate of inflation between $t$ and $ t+1$;
+* $\pi_t^*$ be the public's expected rate of inflation between $t$ and $t+1$;
+* $T$ the horizon -- i.e., the last period for which the model will determine $p_t$
+* $\pi_{T+1}^*$ the terminal rate of inflation between times $T$ and $T+1$.
+
+The demand for real balances $\exp\left(m_t^d - p_t\right)$ is governed by the following version of the Cagan demand function
+
+$$
+m_t^d - p_t = -\alpha \pi_t^* \: , \: \alpha > 0 ; \quad t = 0, 1, \ldots, T .
+$$ (eq:caganmd)
+
+This equation asserts that the demand for real balances
+is inversely related to the public's expected rate of inflation with sensitivity $\alpha$.
+
+People somehow acquire **perfect foresight** by their having solved a forecasting
+problem.
+
+This lets us set
+
+$$
+\pi_t^* = \pi_t , % \forall t
+$$ (eq:ree)
+
+while equating demand for money to supply lets us set $m_t^d = m_t$ for all $t \geq 0$.
+
+The preceding equations then imply
+
+$$
+m_t - p_t = -\alpha(p_{t+1} - p_t)
+$$ (eq:cagan)
+
+To fill in details about what it means for private agents
+to have perfect foresight, we subtract equation {eq}`eq:cagan` at time $ t $ from the same equation at $ t+1$ to get
+
+$$
+\mu_t - \pi_t = -\alpha \pi_{t+1} + \alpha \pi_t ,
+$$
+
+which we rewrite as a forward-looking first-order linear difference
+equation in $\pi_s$ with $\mu_s$ as a "forcing variable":
+
+$$
+\pi_t = \frac{\alpha}{1+\alpha} \pi_{t+1} + \frac{1}{1+\alpha} \mu_t , \quad t= 0, 1, \ldots , T
+$$
+
+where $ 0< \frac{\alpha}{1+\alpha} <1 $.
+
+Setting $\delta =\frac{\alpha}{1+\alpha}$, let's us represent the preceding equation as
+
+$$
+\pi_t = \delta \pi_{t+1} + (1-\delta) \mu_t , \quad t =0, 1, \ldots, T
+$$
+
+Write this system of $T+1$ equations as the single matrix equation
+
+$$
+\begin{bmatrix} 1 & -\delta & 0 & 0 & \cdots & 0 & 0 \cr
+ 0 & 1 & -\delta & 0 & \cdots & 0 & 0 \cr
+ 0 & 0 & 1 & -\delta & \cdots & 0 & 0 \cr
+ \vdots & \vdots & \vdots & \vdots & \vdots & -\delta & 0 \cr
+ 0 & 0 & 0 & 0 & \cdots & 1 & -\delta \cr
+ 0 & 0 & 0 & 0 & \cdots & 0 & 1 \end{bmatrix}
+\begin{bmatrix} \pi_0 \cr \pi_1 \cr \pi_2 \cr \vdots \cr \pi_{T-1} \cr \pi_T
+\end{bmatrix}
+= (1 - \delta) \begin{bmatrix}
+\mu_0 \cr \mu_1 \cr \mu_2 \cr \vdots \cr \mu_{T-1} \cr \mu_T
+\end{bmatrix}
++ \begin{bmatrix}
+0 \cr 0 \cr 0 \cr \vdots \cr 0 \cr \delta \pi_{T+1}^*
+\end{bmatrix}
+$$ (eq:pieq)
+
+By multiplying both sides of equation {eq}`eq:pieq` by the inverse of the matrix on the left side, we can calculate
+
+$$
+\pi \equiv \begin{bmatrix} \pi_0 \cr \pi_1 \cr \pi_2 \cr \vdots \cr \pi_{T-1} \cr \pi_T
+\end{bmatrix}
+$$
+
+It turns out that
+
+$$
+\pi_t = (1-\delta) \sum_{s=t}^T \delta^{s-t} \mu_s + \delta^{T+1-t} \pi_{T+1}^*
+$$ (eq:fisctheory1)
+
+We can represent the equations
+
+$$
+m_{t+1} = m_t + \mu_t , \quad t = 0, 1, \ldots, T
+$$
+
+as the matrix equation
+
+$$
+\begin{bmatrix}
+1 & 0 & 0 & \cdots & 0 & 0 \cr
+-1 & 1 & 0 & \cdots & 0 & 0 \cr
+0 & -1 & 1 & \cdots & 0 & 0 \cr
+\vdots & \vdots & \vdots & \vdots & 0 & 0 \cr
+0 & 0 & 0 & \cdots & 1 & 0 \cr
+0 & 0 & 0 & \cdots & -1 & 1
+\end{bmatrix}
+\begin{bmatrix}
+m_1 \cr m_2 \cr m_3 \cr \vdots \cr m_T \cr m_{T+1}
+\end{bmatrix}
+= \begin{bmatrix}
+\mu_0 \cr \mu_1 \cr \mu_2 \cr \vdots \cr \mu_{T-1} \cr \mu_T
+\end{bmatrix}
++ \begin{bmatrix}
+m_0 \cr 0 \cr 0 \cr \vdots \cr 0 \cr 0
+\end{bmatrix}
+$$ (eq:eq101)
+
+Multiplying both sides of equation {eq}`eq:eq101` with the inverse of the matrix on the left will give
+
+$$
+m_t = m_0 + \sum_{s=0}^{t-1} \mu_s, \quad t =1, \ldots, T+1
+$$ (eq:mcum)
+
+Equation {eq}`eq:mcum` shows that the log of the money supply at $t$ equals the log of the initial money supply $m_0$
+plus accumulation of rates of money growth between times $0$ and $T$.
+
+## Continuation values
+
+To determine the continuation inflation rate $\pi_{T+1}^*$ we shall proceed by applying the following infinite-horizon
+version of equation {eq}`eq:fisctheory1` at time $t = T+1$:
+
+$$
+\pi_t = (1-\delta) \sum_{s=t}^\infty \delta^{s-t} \mu_s ,
+$$ (eq:fisctheory2)
+
+and by also assuming the following continuation path for $\mu_t$ beyond $T$:
+
+$$
+\mu_{t+1} = \gamma^* \mu_t, \quad t \geq T .
+$$
+
+Plugging the preceding equation into equation {eq}`eq:fisctheory2` at $t = T+1$ and rearranging we can deduce that
+
+$$
+\pi_{T+1}^* = \frac{1 - \delta}{1 - \delta \gamma^*} \gamma^* \mu_T
+$$ (eq:piterm)
+
+where we require that $\vert \gamma^* \delta \vert < 1$.
+
+Let's implement and solve this model.
+
+
+As usual, we'll start by importing some Python modules.
+
+```{code-cell} ipython3
+import numpy as np
+from collections import namedtuple
+import matplotlib.pyplot as plt
+```
+
+First, we store parameters in a `namedtuple`:
+
+```{code-cell} ipython3
+# Create the rational expectation version of Cagan model in finite time
+CaganREE = namedtuple("CaganREE",
+ ["m0", # initial money supply
+ "μ_seq", # sequence of rate of growth
+ "α", # sensitivity parameter
+ "δ", # α/(1 + α)
+ "π_end" # terminal expected inflation
+ ])
+
+def create_cagan_model(m0=1, α=5, μ_seq=None):
+ δ = α/(1 + α)
+ π_end = μ_seq[-1] # compute terminal expected inflation
+ return CaganREE(m0, μ_seq, α, δ, π_end)
+```
+
+Now we can solve the model to compute $\pi_t$, $m_t$ and $p_t$ for $t =1, \ldots, T+1$ using the matrix equation above
+
+```{code-cell} ipython3
+def solve(model, T):
+ m0, π_end, μ_seq, α, δ = (model.m0, model.π_end,
+ model.μ_seq, model.α, model.δ)
+
+ # Create matrix representation above
+ A1 = np.eye(T+1, T+1) - δ * np.eye(T+1, T+1, k=1)
+ A2 = np.eye(T+1, T+1) - np.eye(T+1, T+1, k=-1)
+
+ b1 = (1-δ) * μ_seq + np.concatenate([np.zeros(T), [δ * π_end]])
+ b2 = μ_seq + np.concatenate([[m0], np.zeros(T)])
+
+ π_seq = np.linalg.solve(A1, b1)
+ m_seq = np.linalg.solve(A2, b2)
+
+ π_seq = np.append(π_seq, π_end)
+ m_seq = np.append(m0, m_seq)
+
+ p_seq = m_seq + α * π_seq
+
+ return π_seq, m_seq, p_seq
+```
+
+### Some quantitative experiments
+
+In the experiments below, we'll use formula {eq}`eq:piterm` as our terminal condition for expected inflation.
+
+In devising these experiments, we'll make assumptions about $\{\mu_t\}$ that are consistent with formula
+{eq}`eq:piterm`.
+
+We describe several such experiments.
+
+In all of them,
+
+$$
+\mu_t = \mu^* , \quad t \geq T_1
+$$
+
+so that, in terms of our notation and formula for $\pi_{T+1}^*$ above, $\gamma^* = 1$.
+
+#### Experiment 1: Foreseen sudden stabilization
+
+In this experiment, we'll study how, when $\alpha >0$, a foreseen inflation stabilization has effects on inflation that proceed it.
+
+We'll study a situation in which the rate of growth of the money supply is $\mu_0$
+from $t=0$ to $t= T_1$ and then permanently falls to $\mu^*$ at $t=T_1$.
+
+Thus, let $T_1 \in (0, T)$.
+
+So where $\mu_0 > \mu^*$, we assume that
+
+$$
+\mu_{t+1} = \begin{cases}
+ \mu_0 , & t = 0, \ldots, T_1 -1 \\
+ \mu^* , & t \geq T_1
+ \end{cases}
+$$
+
+We'll start by executing a version of our "experiment 1" in which the government implements a _foreseen_ sudden permanent reduction in the rate of money creation at time $T_1$.
+
+Let's experiment with the following parameters
+
+```{code-cell} ipython3
+T1 = 60
+μ0 = 0.5
+μ_star = 0
+T = 80
+
+μ_seq_1 = np.append(μ0*np.ones(T1+1), μ_star*np.ones(T-T1))
+
+cm = create_cagan_model(μ_seq=μ_seq_1)
+
+# solve the model
+π_seq_1, m_seq_1, p_seq_1 = solve(cm, T)
+```
+
+Now we use the following function to plot the result
+
+```{code-cell} ipython3
+def plot_sequences(sequences, labels):
+ fig, axs = plt.subplots(len(sequences), 1, figsize=(5, 12), dpi=200)
+ for ax, seq, label in zip(axs, sequences, labels):
+ ax.plot(range(len(seq)), seq, label=label)
+ ax.set_ylabel(label)
+ ax.set_xlabel('$t$')
+ ax.legend()
+ plt.tight_layout()
+ plt.show()
+
+sequences = (μ_seq_1, π_seq_1, m_seq_1 - p_seq_1, m_seq_1, p_seq_1)
+plot_sequences(sequences, (r'$\mu$', r'$\pi$', r'$m - p$', r'$m$', r'$p$'))
+```
+
+The plot of the money growth rate $\mu_t$ in the top level panel portrays
+a sudden reduction from $.5$ to $0$ at time $T_1 = 60$.
+
+This brings about a gradual reduction of the inflation rate $\pi_t$ that precedes the
+money supply growth rate reduction at time $T_1$.
+
+Notice how the inflation rate declines smoothly (i.e., continuously) to $0$ at $T_1$ --
+unlike the money growth rate, it does not suddenly "jump" downward at $T_1$.
+
+This is because the reduction in $\mu$ at $T_1$ has been foreseen from the start.
+
+While the log money supply portrayed in the bottom panel has a kink at $T_1$, the log price level does not -- it is "smooth" -- once again a consequence of the fact that the
+reduction in $\mu$ has been foreseen.
+
+To set the stage for our next experiment, we want to study the determinants of the price level a little more.
+
+
+### The log price level
+
+We can use equations {eq}`eq:caganmd` and {eq}`eq:ree`
+to discover that the log of the price level satisfies
+
+$$
+p_t = m_t + \alpha \pi_t
+$$ (eq:pformula2)
+
+or, by using equation {eq}`eq:fisctheory1`,
+
+$$
+p_t = m_t + \alpha \left[ (1-\delta) \sum_{s=t}^T \delta^{s-t} \mu_s + \delta^{T+1-t} \pi_{T+1}^* \right]
+$$ (eq:pfiscaltheory2)
+
+In our next experiment, we'll study a "surprise" permanent change in the money growth that beforehand
+was completely unanticipated.
+
+At time $T_1$ when the "surprise" money growth rate change occurs, to satisfy
+equation {eq}`eq:pformula2`, the log of real balances jumps
+_upward_ as $\pi_t$ jumps _downward_.
+
+But in order for $m_t - p_t$ to jump, which variable jumps, $m_{T_1}$ or $p_{T_1}$?
+
+We'll study that interesting question next.
+
+### What jumps?
+
+What jumps at $T_1$?
+
+Is it $p_{T_1}$ or $m_{T_1}$?
+
+If we insist that the money supply $m_{T_1}$ is locked at its value $m_{T_1}^1$ inherited from the past, then formula {eq}`eq:pformula2` implies that the price level jumps downward at time $T_1$, to coincide with the downward jump in
+$\pi_{T_1}$
+
+An alternative assumption about the money supply level is that as part of the "inflation stabilization",
+the government resets $m_{T_1}$ according to
+
+$$
+m_{T_1}^2 - m_{T_1}^1 = \alpha (\pi_{T_1}^1 - \pi_{T_1}^2),
+$$ (eq:eqnmoneyjump)
+
+which describes how the government could reset the money supply at $T_1$ in response to the jump in expected inflation associated with monetary stabilization.
+
+Doing this would let the price level be continuous at $T_1$.
+
+By letting money jump according to equation {eq}`eq:eqnmoneyjump` the monetary authority prevents the price level from _falling_ at the moment that the unanticipated stabilization arrives.
+
+In various research papers about stabilizations of high inflations, the jump in the money supply described by equation {eq}`eq:eqnmoneyjump` has been called
+"the velocity dividend" that a government reaps from implementing a regime change that sustains a permanently lower inflation rate.
+
+#### Technical details about whether $p$ or $m$ jumps at $T_1$
+
+We have noted that with a constant expected forward sequence $\mu_s = \bar \mu$ for $s\geq t$, $\pi_{t} =\bar{\mu}$.
+
+A consequence is that at $T_1$, either $m$ or $p$ must "jump" at $T_1$.
+
+We'll study both cases.
+
+#### $m_{T_{1}}$ does not jump.
+
+$$
+\begin{aligned}
+m_{T_{1}}&=m_{T_{1}-1}+\mu_{0}\\\pi_{T_{1}}&=\mu^{*}\\p_{T_{1}}&=m_{T_{1}}+\alpha\pi_{T_{1}}
+\end{aligned}
+$$
+
+Simply glue the sequences $t\leq T_1$ and $t > T_1$.
+
+#### $m_{T_{1}}$ jumps.
+
+We reset $m_{T_{1}}$ so that $p_{T_{1}}=\left(m_{T_{1}-1}+\mu_{0}\right)+\alpha\mu_{0}$, with $\pi_{T_{1}}=\mu^{*}$.
+
+Then,
+
+$$
+m_{T_{1}}=p_{T_{1}}-\alpha\pi_{T_{1}}=\left(m_{T_{1}-1}+\mu_{0}\right)+\alpha\left(\mu_{0}-\mu^{*}\right)
+$$
+
+We then compute for the remaining $T-T_{1}$ periods with $\mu_{s}=\mu^{*},\forall s\geq T_{1}$ and the initial condition $m_{T_{1}}$ from above.
+
+We are now technically equipped to discuss our next experiment.
+
+#### Experiment 2: an unforeseen sudden stabilization
+
+This experiment deviates a little bit from a pure version of our "perfect foresight"
+assumption by assuming that a sudden permanent reduction in $\mu_t$ like that
+analyzed in experiment 1 is completely unanticipated.
+
+Such a completely unanticipated shock is popularly known as an "MIT shock".
+
+The mental experiment involves switching at time $T_1$ from an initial "continuation path" for $\{\mu_t, \pi_t\} $ to another path that involves a permanently lower inflation rate.
+
+**Initial Path:** $\mu_t = \mu_0$ for all $t \geq 0$. So this path is for $\{\mu_t\}_{t=0}^\infty$; the associated
+path for $\pi_t$ has $\pi_t = \mu_0$.
+
+**Revised Continuation Path** Where $ \mu_0 > \mu^*$, we construct a continuation path $\{\mu_s\}_{s=T_1}^\infty$
+by setting $\mu_s = \mu^*$ for all $s \geq T_1$. The perfect foresight continuation path for
+$\pi$ is $\pi_s = \mu^*$
+
+To capture a "completely unanticipated permanent shock to the $\{\mu_t\}$ process at time $T_1$, we simply glue the $\mu_t, \pi_t$
+that emerges under path 2 for $t \geq T_1$ to the $\mu_t, \pi_t$ path that had emerged under path 1 for $ t=0, \ldots,
+T_1 -1$.
+
+We can do the MIT shock calculations mostly by hand.
+
+Thus, for path 1, $\pi_t = \mu_0 $ for all $t \in [0, T_1-1]$, while for path 2,
+$\mu_s = \mu^*$ for all $s \geq T_1$.
+
+We now move on to experiment 2, our "MIT shock", completely unforeseen
+sudden stabilization.
+
+We set this up so that the $\{\mu_t\}$ sequences that describe the sudden stabilization
+are identical to those for experiment 1, the foreseen sudden stabilization.
+
+The following code does the calculations and plots outcomes.
+
+```{code-cell} ipython3
+# path 1
+μ_seq_2_path1 = μ0 * np.ones(T+1)
+
+cm1 = create_cagan_model(μ_seq=μ_seq_2_path1)
+π_seq_2_path1, m_seq_2_path1, p_seq_2_path1 = solve(cm1, T)
+
+# continuation path
+μ_seq_2_cont = μ_star * np.ones(T-T1)
+
+cm2 = create_cagan_model(m0=m_seq_2_path1[T1+1],
+ μ_seq=μ_seq_2_cont)
+π_seq_2_cont, m_seq_2_cont1, p_seq_2_cont1 = solve(cm2, T-1-T1)
+
+
+# regime 1 - simply glue π_seq, μ_seq
+μ_seq_2 = np.concatenate((μ_seq_2_path1[:T1+1],
+ μ_seq_2_cont))
+π_seq_2 = np.concatenate((π_seq_2_path1[:T1+1],
+ π_seq_2_cont))
+m_seq_2_regime1 = np.concatenate((m_seq_2_path1[:T1+1],
+ m_seq_2_cont1))
+p_seq_2_regime1 = np.concatenate((p_seq_2_path1[:T1+1],
+ p_seq_2_cont1))
+
+# regime 2 - reset m_T1
+m_T1 = (m_seq_2_path1[T1] + μ0) + cm2.α*(μ0 - μ_star)
+
+cm3 = create_cagan_model(m0=m_T1, μ_seq=μ_seq_2_cont)
+π_seq_2_cont2, m_seq_2_cont2, p_seq_2_cont2 = solve(cm3, T-1-T1)
+
+m_seq_2_regime2 = np.concatenate((m_seq_2_path1[:T1+1],
+ m_seq_2_cont2))
+p_seq_2_regime2 = np.concatenate((p_seq_2_path1[:T1+1],
+ p_seq_2_cont2))
+```
+
+```{code-cell} ipython3
+:tags: [hide-input]
+
+T_seq = range(T+2)
+
+# plot both regimes
+fig, ax = plt.subplots(5, 1, figsize=(5, 12), dpi=200)
+
+# Configuration for each subplot
+plot_configs = [
+ {'data': [(T_seq[:-1], μ_seq_2)], 'ylabel': r'$\mu$'},
+ {'data': [(T_seq, π_seq_2)], 'ylabel': r'$\pi$'},
+ {'data': [(T_seq, m_seq_2_regime1 - p_seq_2_regime1)],
+ 'ylabel': r'$m - p$'},
+ {'data': [(T_seq, m_seq_2_regime1, 'Smooth $m_{T_1}$'),
+ (T_seq, m_seq_2_regime2, 'Jumpy $m_{T_1}$')],
+ 'ylabel': r'$m$'},
+ {'data': [(T_seq, p_seq_2_regime1, 'Smooth $p_{T_1}$'),
+ (T_seq, p_seq_2_regime2, 'Jumpy $p_{T_1}$')],
+ 'ylabel': r'$p$'}
+]
+
+def experiment_plot(plot_configs, ax):
+ # Loop through each subplot configuration
+ for axi, config in zip(ax, plot_configs):
+ for data in config['data']:
+ if len(data) == 3: # Plot with label for legend
+ axi.plot(data[0], data[1], label=data[2])
+ axi.legend()
+ else: # Plot without label
+ axi.plot(data[0], data[1])
+ axi.set_ylabel(config['ylabel'])
+ axi.set_xlabel(r'$t$')
+ plt.tight_layout()
+ plt.show()
+
+experiment_plot(plot_configs, ax)
+```
+
+We invite you to compare these graphs with corresponding ones for the foreseen stabilization analyzed in experiment 1 above.
+
+Note how the inflation graph in the second panel is now identical to the
+money growth graph in the top panel, and how now the log of real balances portrayed in the third panel jumps upward at time $T_1$.
+
+The bottom two panels plot $m$ and $p$ under two possible ways that $m_{T_1}$ might adjust
+as required by the upward jump in $m - p$ at $T_1$.
+
+* the orange line lets $m_{T_1}$ jump upward in order to make sure that the log price level $p_{T_1}$ does not fall.
+
+* the blue line lets $p_{T_1}$ fall while stopping the money supply from jumping.
+
+Here is a way to interpret what the government is doing when the orange line policy is in place.
+
+The government prints money to finance expenditure with the "velocity dividend" that it reaps from the increased demand for real balances brought about by the permanent decrease in the rate of growth of the money supply.
+
+The next code generates a multi-panel graph that includes outcomes of both experiments 1 and 2.
+
+That allows us to assess how important it is to understand whether the sudden permanent drop in $\mu_t$ at $t=T_1$ is fully unanticipated, as in experiment 1, or completely
+unanticipated, as in experiment 2.
+
+```{code-cell} ipython3
+:tags: [hide-input]
+
+# compare foreseen vs unforeseen shock
+fig, ax = plt.subplots(5, figsize=(5, 12), dpi=200)
+
+plot_configs = [
+ {'data': [(T_seq[:-1], μ_seq_2)], 'ylabel': r'$\mu$'},
+ {'data': [(T_seq, π_seq_2, 'Unforeseen'),
+ (T_seq, π_seq_1, 'Foreseen')], 'ylabel': r'$p$'},
+ {'data': [(T_seq, m_seq_2_regime1 - p_seq_2_regime1, 'Unforeseen'),
+ (T_seq, m_seq_1 - p_seq_1, 'Foreseen')], 'ylabel': r'$m - p$'},
+ {'data': [(T_seq, m_seq_2_regime1, 'Unforeseen (Smooth $m_{T_1}$)'),
+ (T_seq, m_seq_2_regime2, 'Unforeseen ($m_{T_1}$ jumps)'),
+ (T_seq, m_seq_1, 'Foreseen')], 'ylabel': r'$m$'},
+ {'data': [(T_seq, p_seq_2_regime1, 'Unforeseen (Smooth $m_{T_1}$)'),
+ (T_seq, p_seq_2_regime2, 'Unforeseen ($m_{T_1}$ jumps)'),
+ (T_seq, p_seq_1, 'Foreseen')], 'ylabel': r'$p$'}
+]
+
+experiment_plot(plot_configs, ax)
+```
+
+It is instructive to compare the preceding graphs with graphs of log price levels and inflation rates for data from four big inflations described in
+{doc}`this lecture `.
+
+In particular, in the above graphs, notice how a gradual fall in inflation precedes the "sudden stop" when it has been anticipated long beforehand, but how
+inflation instead falls abruptly when the permanent drop in money supply growth is unanticipated.
+
+It seems to the author team at quantecon that the drops in inflation near the ends of the four hyperinflations described in {doc}`this lecture `
+more closely resemble outcomes from the experiment 2 "unforeseen stabilization".
+
+(It is fair to say that the preceding informal pattern recognition exercise should be supplemented with a more formal structural statistical analysis.)
+
+#### Experiment 3
+
+**Foreseen gradual stabilization**
+
+Instead of a foreseen sudden stabilization of the type studied with experiment 1,
+it is also interesting to study the consequences of a foreseen gradual stabilization.
+
+Thus, suppose that $\phi \in (0,1)$, that $\mu_0 > \mu^*$, and that for $t = 0, \ldots, T-1$
+
+$$
+\mu_t = \phi^t \mu_0 + (1 - \phi^t) \mu^* .
+$$
+
+Next we perform an experiment in which there is a perfectly foreseen _gradual_ decrease in the rate of growth of the money supply.
+
+The following code does the calculations and plots the results.
+
+```{code-cell} ipython3
+# parameters
+ϕ = 0.9
+μ_seq_stab = np.array([ϕ**t * μ0 + (1-ϕ**t)*μ_star for t in range(T)])
+μ_seq_stab = np.append(μ_seq_stab, μ_star)
+
+cm4 = create_cagan_model(μ_seq=μ_seq_stab)
+
+π_seq_4, m_seq_4, p_seq_4 = solve(cm4, T)
+
+sequences = (μ_seq_stab, π_seq_4,
+ m_seq_4 - p_seq_4, m_seq_4, p_seq_4)
+plot_sequences(sequences, (r'$\mu$', r'$\pi$',
+ r'$m - p$', r'$m$', r'$p$'))
+```
+
+## Sequel
+
+Another lecture {doc}`monetarist theory of price levels with adaptive expectations ` describes an "adaptive expectations" version of Cagan's model.
+
+The dynamics become more complicated and so does the algebra.
+
+Nowadays, the "rational expectations" version of the model is more popular among central bankers and economists advising them.
diff --git a/content/lectures/cobweb.ipynb b/book/_build/html/_sources/cobweb.ipynb
similarity index 86%
rename from content/lectures/cobweb.ipynb
rename to book/_build/html/_sources/cobweb.ipynb
index 64bc44e..ea35586 100644
--- a/content/lectures/cobweb.ipynb
+++ b/book/_build/html/_sources/cobweb.ipynb
@@ -2,13 +2,12 @@
"cells": [
{
"cell_type": "markdown",
- "id": "7615683b",
+ "id": "51c14ade",
"metadata": {},
"source": [
"(cobweb)=\n",
"# The Cobweb Model\n",
"\n",
- "\n",
"The cobweb model is a model of prices and quantities in a given market, and how they evolve over time.\n",
"\n",
"## Overview \n",
@@ -18,7 +17,7 @@
"\n",
"To give some idea of how the model operates, and why expectations matter, imagine the following scenario.\n",
"\n",
- "There is a market for soy beans, say, where prices and traded quantities\n",
+ "There is a market for soybeans, say, where prices and traded quantities\n",
"depend on the choices of buyers and sellers.\n",
"\n",
"The buyers are represented by a demand curve --- they buy more at low prices\n",
@@ -32,11 +31,11 @@
"Suppose now that the price is currently high.\n",
"\n",
"Seeing this high price, and perhaps expecting that the high price will remain\n",
- "for some time, the farmers plant many fields with soy beans.\n",
+ "for some time, the farmers plant many fields with soybeans.\n",
"\n",
"Next period the resulting high supply floods the market, causing the price to drop.\n",
"\n",
- "Seeing this low price, the farmers now shift out of soy beans, restricting\n",
+ "Seeing this low price, the farmers now shift out of soybeans, restricting\n",
"supply and causing the price to climb again.\n",
"\n",
"You can imagine how these dynamics could cause cycles in prices and quantities\n",
@@ -46,23 +45,17 @@
"them, and to study conditions under which cycles persist (or disappear).\n",
"\n",
"In this lecture, we investigate and simulate the basic model under different\n",
- "assumptions regarding the way that produces form expectations.\n",
+ "assumptions regarding the way that producers form expectations.\n",
+ "\n",
+ "Our discussion and simulations draw on [high quality lectures](https://comp-econ.org/CEF_2013/downloads/Complex%20Econ%20Systems%20Lecture%20II.pdf) by [Cars Hommes](https://www.uva.nl/en/profile/h/o/c.h.hommes/c.h.hommes.html).\n",
"\n",
- "Our discussion and simulations draw on [high quality lectures](https://comp-econ.org/CEF_2013/downloads/Complex%20Econ%20Systems%20Lecture%20II.pdf) by [Cars Hommes](https://www.uva.nl/en/profile/h/o/c.h.hommes/c.h.hommes.html)."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "353ee1d8",
- "metadata": {},
- "source": [
"We will use the following imports."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "eb6bcc0d",
+ "id": "35239c06",
"metadata": {},
"outputs": [],
"source": [
@@ -72,14 +65,14 @@
},
{
"cell_type": "markdown",
- "id": "ce16e184",
+ "id": "43d8154d",
"metadata": {},
"source": [
"## History\n",
"\n",
"Early papers on the cobweb cycle include {cite}`cobweb_model` and {cite}`hog_cycle`.\n",
"\n",
- "The paper {cite}`hog_cycle` uses the cobweb theorem to explain the prices of hog in the US over 1920--1950\n",
+ "The paper {cite}`hog_cycle` uses the cobweb theorem to explain the prices of hog in the US over 1920--1950.\n",
"\n",
"The next plot replicates part of Figure 2 from that paper, which plots the price of hogs at yearly frequency.\n",
"\n",
@@ -89,7 +82,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "adafd9b0",
+ "id": "f39d83c9",
"metadata": {},
"outputs": [],
"source": [
@@ -108,14 +101,14 @@
},
{
"cell_type": "markdown",
- "id": "67929476",
+ "id": "c5254a00",
"metadata": {},
"source": [
- "## The Model\n",
+ "## The model\n",
"\n",
- "Let's return to our discussion of a hypothetical soy bean market, where price is determined by supply and demand.\n",
+ "Let's return to our discussion of a hypothetical soybean market, where price is determined by supply and demand.\n",
"\n",
- "We suppose that demand for soy beans is given by\n",
+ "We suppose that demand for soybeans is given by\n",
"\n",
"$$\n",
" D(p_t) = a - b p_t\n",
@@ -125,15 +118,15 @@
"\n",
"($D(p_t)$ is the quantity demanded in some fixed unit, such as thousands of tons.)\n",
"\n",
- "Because the crop of soy beans for time $t$ is planted at $t-1$, supply of soy beans at time $t$ depends on *expected* prices at time $t$, which we denote $p^e_{t-1}$.\n",
+ "Because the crop of soybeans for time $t$ is planted at $t-1$, supply of soybeans at time $t$ depends on *expected* prices at time $t$, which we denote $p^e_t$.\n",
"\n",
"We suppose that supply is nonlinear in expected prices, and takes the form\n",
"\n",
"$$\n",
- " S(p^e_{t-1}) = \\tanh(\\lambda(p^e_{t-1} - c)) + d\n",
+ " S(p^e_t) = \\tanh(\\lambda(p^e_t - c)) + d\n",
"$$\n",
"\n",
- "where $\\lambda$ is a positive constant and $c, d \\geq 0$.\n",
+ "where $\\lambda$ is a positive constant, $c, d$ are nonnegative constants and $\\tanh$ is a type of [hyperbolic function](https://en.wikipedia.org/wiki/Hyperbolic_functions).\n",
"\n",
"Let's make a plot of supply and demand for particular choices of the parameter values.\n",
"\n",
@@ -143,7 +136,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "46b48306",
+ "id": "13205c87",
"metadata": {},
"outputs": [],
"source": [
@@ -169,7 +162,7 @@
},
{
"cell_type": "markdown",
- "id": "6167427e",
+ "id": "7d9d74c5",
"metadata": {},
"source": [
"Now let's plot."
@@ -178,7 +171,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "21a325c2",
+ "id": "98a6c898",
"metadata": {},
"outputs": [],
"source": [
@@ -187,7 +180,7 @@
"fig, ax = plt.subplots()\n",
"\n",
"ax.plot(p_grid, m.demand(p_grid), label=\"$D$\")\n",
- "ax.plot(p_grid, m.supply(p_grid), label=\"S\")\n",
+ "ax.plot(p_grid, m.supply(p_grid), label=\"$S$\")\n",
"ax.set_xlabel(\"price\")\n",
"ax.set_ylabel(\"quantity\")\n",
"ax.legend()\n",
@@ -197,19 +190,19 @@
},
{
"cell_type": "markdown",
- "id": "7835721d",
+ "id": "1874274c",
"metadata": {},
"source": [
"Market equilibrium requires that supply equals demand, or\n",
"\n",
"$$\n",
- " a - b p_t = S(p^e_{t-1})\n",
+ " a - b p_t = S(p^e_t)\n",
"$$\n",
"\n",
"Rewriting in terms of $p_t$ gives\n",
"\n",
"$$\n",
- " p_t = - \\frac{1}{b} [S(p^e_{t-1}) - a]\n",
+ " p_t = - \\frac{1}{b} [S(p^e_t) - a]\n",
"$$\n",
"\n",
"Finally, to complete the model, we need to describe how price expectations are formed.\n",
@@ -220,7 +213,7 @@
"\n",
"```{math}\n",
":label: p_et\n",
- " p^e_{t-1} = f(p_{t-1}, p_{t-2})\n",
+ " p^e_t = f(p_{t-1}, p_{t-2})\n",
"```\n",
"\n",
"where $f$ is some function.\n",
@@ -238,8 +231,7 @@
"\n",
"The price dynamics depend on the parameter values and also on the function $f$ that determines how producers form expectations.\n",
"\n",
- "\n",
- "## Naive Expectations\n",
+ "## Naive expectations\n",
"\n",
"To go further in our analysis we need to specify the function $f$; that is, how expectations are formed.\n",
"\n",
@@ -247,7 +239,9 @@
"\n",
"In other words,\n",
"\n",
- "$$ p_{t-1}^e = p_{t-1} $$\n",
+ "$$ \n",
+ "p_t^e = p_{t-1} \n",
+ "$$\n",
"\n",
"Using {eq}`price_t`, we then have\n",
"\n",
@@ -268,14 +262,13 @@
" g(p) = - \\frac{1}{b} [ S(p) - a]\n",
"```\n",
"\n",
- "\n",
"Here we represent the function $g$"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "5842c03b",
+ "id": "12ebe7dc",
"metadata": {},
"outputs": [],
"source": [
@@ -291,18 +284,18 @@
},
{
"cell_type": "markdown",
- "id": "32fe9c96",
+ "id": "4fed2d19",
"metadata": {},
"source": [
- "Let's try to understand how prices will evolve using a 45 degree diagram, which is a tool for studying one-dimensional dynamics.\n",
+ "Let's try to understand how prices will evolve using a 45-degree diagram, which is a tool for studying one-dimensional dynamics.\n",
"\n",
- "The function `plot45` defined below helps us draw the 45 degree diagram."
+ "The function `plot45` defined below helps us draw the 45-degree diagram."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "d16435f7",
+ "id": "4c7c7ff8",
"metadata": {
"tags": [
"hide-input"
@@ -341,7 +334,7 @@
"\n",
" ax.plot(pgrid, g(model, pgrid), 'b-',\n",
" lw=2, alpha=0.6, label='g')\n",
- " ax.plot(pgrid, pgrid, lw=1, alpha=0.7, label='45')\n",
+ " ax.plot(pgrid, pgrid, lw=1, alpha=0.7, label='$45\\degree$')\n",
"\n",
" x = p0\n",
" xticks = [pmin]\n",
@@ -368,6 +361,8 @@
"\n",
" xticks.append(pmax)\n",
" xtick_labels.append(pmax)\n",
+ " ax.set_ylabel(r'$p_{t+1}$')\n",
+ " ax.set_xlabel(r'$p_t$')\n",
" ax.set_xticks(xticks)\n",
" ax.set_yticks(xticks)\n",
" ax.set_xticklabels(xtick_labels)\n",
@@ -382,16 +377,16 @@
},
{
"cell_type": "markdown",
- "id": "3a6910a8",
+ "id": "328966ce",
"metadata": {},
"source": [
- "Now we can set up a market and plot the 45 degree diagram."
+ "Now we can set up a market and plot the 45-degree diagram."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "7e8d03eb",
+ "id": "0d28181b",
"metadata": {},
"outputs": [],
"source": [
@@ -401,7 +396,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "85366335",
+ "id": "9909a45e",
"metadata": {},
"outputs": [],
"source": [
@@ -410,10 +405,10 @@
},
{
"cell_type": "markdown",
- "id": "528d4220",
+ "id": "d8cd3000",
"metadata": {},
"source": [
- "The plot shows the function $g$ defined in {eq}`def_g` and the $45$ degree line.\n",
+ "The plot shows the function $g$ defined in {eq}`def_g` and the 45-degree line.\n",
"\n",
"Think of $ p_t $ as a value on the horizontal axis.\n",
"\n",
@@ -421,13 +416,13 @@
"\n",
"Clearly,\n",
"\n",
- "- If $ g $ lies above the 45 degree line at $p_t$, then we have $ p_{t+1} > p_t $.\n",
- "- If $ g $ lies below the 45 degree line at $p_t$, then we have $ p_{t+1} < p_t $.\n",
- "- If $ g $ hits the 45 degree line at $p_t$, then we have $ p_{t+1} = p_t $, so $ p_t $ is a steady state.\n",
+ "- If $ g $ lies above the 45-degree line at $p_t$, then we have $ p_{t+1} > p_t $.\n",
+ "- If $ g $ lies below the 45-degree line at $p_t$, then we have $ p_{t+1} < p_t $.\n",
+ "- If $ g $ hits the 45-degree line at $p_t$, then we have $ p_{t+1} = p_t $, so $ p_t $ is a steady state.\n",
"\n",
"Consider the sequence of prices starting at $p_0$, as shown in the figure.\n",
"\n",
- "We find $p_1$ on the vertical axis and then shift it to the horizontal axis using the 45 degree line (where values on the two axes are equal).\n",
+ "We find $p_1$ on the vertical axis and then shift it to the horizontal axis using the 45-degree line (where values on the two axes are equal).\n",
"\n",
"Then from $p_1$ we obtain $p_2$ and continue.\n",
"\n",
@@ -439,7 +434,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "204328fe",
+ "id": "c4194ad9",
"metadata": {},
"outputs": [],
"source": [
@@ -473,7 +468,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "08dc28fa",
+ "id": "f169121c",
"metadata": {},
"outputs": [],
"source": [
@@ -482,7 +477,7 @@
},
{
"cell_type": "markdown",
- "id": "69406b94",
+ "id": "b888df1c",
"metadata": {},
"source": [
"We see that a cycle has formed and the cycle is persistent.\n",
@@ -497,7 +492,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "a9ded11a",
+ "id": "834776bd",
"metadata": {},
"outputs": [],
"source": [
@@ -506,10 +501,10 @@
},
{
"cell_type": "markdown",
- "id": "9544893f",
+ "id": "4e91a8b6",
"metadata": {},
"source": [
- "## Adaptive Expectations\n",
+ "## Adaptive expectations\n",
"\n",
"Naive expectations are quite simple and also important in driving the cycle that we found.\n",
"\n",
@@ -525,7 +520,7 @@
"\n",
"```{math}\n",
":label: pe_adaptive\n",
- "p_{t-1}^e = \\alpha p_{t-1} + (1-\\alpha) p^e_{t-2}\n",
+ "p_t^e = \\alpha p_{t-1} + (1-\\alpha) p^e_{t-1}\n",
"\\qquad (0 \\leq \\alpha \\leq 1)\n",
"```\n",
"\n",
@@ -533,7 +528,7 @@
"\n",
"```{math}\n",
":label: pe_adaptive_2\n",
- "p_{t-1}^e = p^e_{t-2} + \\alpha (p_{t-1} - p_{t-2}^e)\n",
+ "p_t^e = p^e_{t-1} + \\alpha (p_{t-1} - p_{t-1}^e)\n",
"```\n",
"\n",
"This equation helps to show that expectations shift\n",
@@ -544,17 +539,16 @@
"Using {eq}`pe_adaptive`, we obtain the dynamics\n",
"\n",
"$$\n",
- " p_t = - \\frac{1}{b} [ S(\\alpha p_{t-1} + (1-\\alpha) p^e_{t-2}) - a]\n",
+ " p_t = - \\frac{1}{b} [ S(\\alpha p_{t-1} + (1-\\alpha) p^e_{t-1}) - a]\n",
"$$\n",
"\n",
- "\n",
"Let's try to simulate the price and observe the dynamics using different values of $\\alpha$."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "205f383f",
+ "id": "b352f06e",
"metadata": {},
"outputs": [],
"source": [
@@ -568,7 +562,7 @@
},
{
"cell_type": "markdown",
- "id": "7827f4d9",
+ "id": "8335632f",
"metadata": {},
"source": [
"The function below plots price dynamics under adaptive expectations for different values of $\\alpha$."
@@ -577,7 +571,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "aa1032c1",
+ "id": "d4e9bfc7",
"metadata": {},
"outputs": [],
"source": [
@@ -600,18 +594,16 @@
},
{
"cell_type": "markdown",
- "id": "cac10b03",
+ "id": "c964a48f",
"metadata": {},
"source": [
- "Let's call the function with prices starting at $p_0 = 5$.\n",
- "\n",
- "TODO does this fit well in the page, even in the pdf? If not should it be stacked vertically?"
+ "Let's call the function with prices starting at $p_0 = 5$."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "4266a97a",
+ "id": "4e20f6a1",
"metadata": {},
"outputs": [],
"source": [
@@ -620,7 +612,7 @@
},
{
"cell_type": "markdown",
- "id": "21a92ba6",
+ "id": "b9a07e4f",
"metadata": {},
"source": [
"Note that if $\\alpha=1$, then adaptive expectations are just naive expectation.\n",
@@ -630,9 +622,6 @@
"\n",
"This increased stability can be seen in the figures.\n",
"\n",
- "\n",
- "TODO check / fix exercises\n",
- "\n",
"## Exercises\n",
"\n",
"```{exercise-start}\n",
@@ -653,7 +642,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "1e382dd6",
+ "id": "a79232f9",
"metadata": {},
"outputs": [],
"source": [
@@ -689,7 +678,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "bf7e2dcb",
+ "id": "1d7fb34c",
"metadata": {},
"outputs": [],
"source": [
@@ -699,7 +688,7 @@
},
{
"cell_type": "markdown",
- "id": "e4d8d771",
+ "id": "99fa2ab2",
"metadata": {},
"source": [
"```{solution-end}\n",
@@ -718,7 +707,7 @@
"\n",
"```{math}\n",
":label: pe_blae\n",
- "p_{t-1}^e = \\alpha p_{t-1} + (1-\\alpha) p_{t-2}\n",
+ "p_t^e = \\alpha p_{t-1} + (1-\\alpha) p_{t-2}\n",
"```\n",
"\n",
"\n",
@@ -735,7 +724,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "f009b457",
+ "id": "8f464b42",
"metadata": {},
"outputs": [],
"source": [
@@ -750,7 +739,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "ba7045ca",
+ "id": "64e12377",
"metadata": {},
"outputs": [],
"source": [
@@ -782,7 +771,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "6010e78c",
+ "id": "c6038a57",
"metadata": {},
"outputs": [],
"source": [
@@ -796,29 +785,65 @@
},
{
"cell_type": "markdown",
- "id": "27de5499",
+ "id": "898768a0",
"metadata": {},
"source": [
"```{solution-end}\n",
"```"
]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "07ae856a",
- "metadata": {},
- "outputs": [],
- "source": []
}
],
"metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.16.2"
+ }
+ },
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
- }
+ },
+ "source_map": [
+ 12,
+ 60,
+ 63,
+ 75,
+ 87,
+ 117,
+ 136,
+ 140,
+ 152,
+ 225,
+ 234,
+ 240,
+ 313,
+ 317,
+ 321,
+ 323,
+ 347,
+ 375,
+ 377,
+ 387,
+ 389,
+ 431,
+ 438,
+ 442,
+ 458,
+ 462,
+ 464,
+ 489,
+ 519,
+ 522,
+ 553,
+ 562,
+ 588,
+ 595
+ ]
},
"nbformat": 4,
"nbformat_minor": 5
-}
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/cobweb.md b/book/_build/html/_sources/cobweb.md
new file mode 100644
index 0000000..31d7181
--- /dev/null
+++ b/book/_build/html/_sources/cobweb.md
@@ -0,0 +1,598 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.16.2
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+(cobweb)=
+# The Cobweb Model
+
+The cobweb model is a model of prices and quantities in a given market, and how they evolve over time.
+
+## Overview
+
+The cobweb model dates back to the 1930s and, while simple, it remains significant
+because it shows the fundamental importance of *expectations*.
+
+To give some idea of how the model operates, and why expectations matter, imagine the following scenario.
+
+There is a market for soybeans, say, where prices and traded quantities
+depend on the choices of buyers and sellers.
+
+The buyers are represented by a demand curve --- they buy more at low prices
+and less at high prices.
+
+The sellers have a supply curve --- they wish to sell more at high prices and
+less at low prices.
+
+However, the sellers (who are farmers) need time to grow their crops.
+
+Suppose now that the price is currently high.
+
+Seeing this high price, and perhaps expecting that the high price will remain
+for some time, the farmers plant many fields with soybeans.
+
+Next period the resulting high supply floods the market, causing the price to drop.
+
+Seeing this low price, the farmers now shift out of soybeans, restricting
+supply and causing the price to climb again.
+
+You can imagine how these dynamics could cause cycles in prices and quantities
+that persist over time.
+
+The cobweb model puts these ideas into equations so we can try to quantify
+them, and to study conditions under which cycles persist (or disappear).
+
+In this lecture, we investigate and simulate the basic model under different
+assumptions regarding the way that producers form expectations.
+
+Our discussion and simulations draw on [high quality lectures](https://comp-econ.org/CEF_2013/downloads/Complex%20Econ%20Systems%20Lecture%20II.pdf) by [Cars Hommes](https://www.uva.nl/en/profile/h/o/c.h.hommes/c.h.hommes.html).
+
+We will use the following imports.
+
+```{code-cell} ipython3
+import numpy as np
+import matplotlib.pyplot as plt
+```
+
+## History
+
+Early papers on the cobweb cycle include {cite}`cobweb_model` and {cite}`hog_cycle`.
+
+The paper {cite}`hog_cycle` uses the cobweb theorem to explain the prices of hog in the US over 1920--1950.
+
+The next plot replicates part of Figure 2 from that paper, which plots the price of hogs at yearly frequency.
+
+Notice the cyclical price dynamics, which match the kind of cyclical soybean price dynamics discussed above.
+
+```{code-cell} ipython3
+hog_prices = [55, 57, 80, 70, 60, 65, 72, 65, 51, 49, 45, 80, 85,
+ 78, 80, 68, 52, 65, 83, 78, 60, 62, 80, 87, 81, 70,
+ 69, 65, 62, 85, 87, 65, 63, 75, 80, 62]
+years = np.arange(1924, 1960)
+fig, ax = plt.subplots()
+ax.plot(years, hog_prices, '-o', ms=4, label='hog price')
+ax.set_xlabel('year')
+ax.set_ylabel('dollars')
+ax.legend()
+ax.grid()
+plt.show()
+```
+
+## The model
+
+Let's return to our discussion of a hypothetical soybean market, where price is determined by supply and demand.
+
+We suppose that demand for soybeans is given by
+
+$$
+ D(p_t) = a - b p_t
+$$
+
+where $a, b$ are nonnegative constants and $p_t$ is the spot (i.e, current market) price at time $t$.
+
+($D(p_t)$ is the quantity demanded in some fixed unit, such as thousands of tons.)
+
+Because the crop of soybeans for time $t$ is planted at $t-1$, supply of soybeans at time $t$ depends on *expected* prices at time $t$, which we denote $p^e_t$.
+
+We suppose that supply is nonlinear in expected prices, and takes the form
+
+$$
+ S(p^e_t) = \tanh(\lambda(p^e_t - c)) + d
+$$
+
+where $\lambda$ is a positive constant, $c, d$ are nonnegative constants and $\tanh$ is a type of [hyperbolic function](https://en.wikipedia.org/wiki/Hyperbolic_functions).
+
+Let's make a plot of supply and demand for particular choices of the parameter values.
+
+First we store the parameters in a class and define the functions above as methods.
+
+```{code-cell} ipython3
+class Market:
+
+ def __init__(self,
+ a=8, # demand parameter
+ b=1, # demand parameter
+ c=6, # supply parameter
+ d=1, # supply parameter
+ λ=2.0): # supply parameter
+ self.a, self.b, self.c, self.d = a, b, c, d
+ self.λ = λ
+
+ def demand(self, p):
+ a, b = self.a, self.b
+ return a - b * p
+
+ def supply(self, p):
+ c, d, λ = self.c, self.d, self.λ
+ return np.tanh(λ * (p - c)) + d
+```
+
+Now let's plot.
+
+```{code-cell} ipython3
+p_grid = np.linspace(5, 8, 200)
+m = Market()
+fig, ax = plt.subplots()
+
+ax.plot(p_grid, m.demand(p_grid), label="$D$")
+ax.plot(p_grid, m.supply(p_grid), label="$S$")
+ax.set_xlabel("price")
+ax.set_ylabel("quantity")
+ax.legend()
+
+plt.show()
+```
+
+Market equilibrium requires that supply equals demand, or
+
+$$
+ a - b p_t = S(p^e_t)
+$$
+
+Rewriting in terms of $p_t$ gives
+
+$$
+ p_t = - \frac{1}{b} [S(p^e_t) - a]
+$$
+
+Finally, to complete the model, we need to describe how price expectations are formed.
+
+We will assume that expected prices at time $t$ depend on past prices.
+
+In particular, we suppose that
+
+```{math}
+:label: p_et
+ p^e_t = f(p_{t-1}, p_{t-2})
+```
+
+where $f$ is some function.
+
+Thus, we are assuming that producers expect the time-$t$ price to be some function of lagged prices, up to $2$ lags.
+
+(We could of course add additional lags and readers are encouraged to experiment with such cases.)
+
+Combining the last two equations gives the dynamics for prices:
+
+```{math}
+:label: price_t
+ p_t = - \frac{1}{b} [ S(f(p_{t-1}, p_{t-2})) - a]
+```
+
+The price dynamics depend on the parameter values and also on the function $f$ that determines how producers form expectations.
+
+## Naive expectations
+
+To go further in our analysis we need to specify the function $f$; that is, how expectations are formed.
+
+Let's start with naive expectations, which refers to the case where producers expect the next period spot price to be whatever the price is in the current period.
+
+In other words,
+
+$$
+p_t^e = p_{t-1}
+$$
+
+Using {eq}`price_t`, we then have
+
+$$
+ p_t = - \frac{1}{b} [ S(p_{t-1}) - a]
+$$
+
+We can write this as
+
+$$
+ p_t = g(p_{t-1})
+$$
+
+where $g$ is the function defined by
+
+```{math}
+:label: def_g
+ g(p) = - \frac{1}{b} [ S(p) - a]
+```
+
+Here we represent the function $g$
+
+```{code-cell} ipython3
+def g(model, current_price):
+ """
+ Function to find the next price given the current price
+ and Market model
+ """
+ a, b = model.a, model.b
+ next_price = - (model.supply(current_price) - a) / b
+ return next_price
+```
+
+Let's try to understand how prices will evolve using a 45-degree diagram, which is a tool for studying one-dimensional dynamics.
+
+The function `plot45` defined below helps us draw the 45-degree diagram.
+
+```{code-cell} ipython3
+:tags: [hide-input]
+
+def plot45(model, pmin, pmax, p0, num_arrows=5):
+ """
+ Function to plot a 45 degree plot
+
+ Parameters
+ ==========
+
+ model: Market model
+
+ pmin: Lower price limit
+
+ pmax: Upper price limit
+
+ p0: Initial value of price (needed to simulate prices)
+
+ num_arrows: Number of simulations to plot
+ """
+ pgrid = np.linspace(pmin, pmax, 200)
+
+ fig, ax = plt.subplots()
+ ax.set_xlim(pmin, pmax)
+ ax.set_ylim(pmin, pmax)
+
+ hw = (pmax - pmin) * 0.01
+ hl = 2 * hw
+ arrow_args = dict(fc="k", ec="k", head_width=hw,
+ length_includes_head=True, lw=1,
+ alpha=0.6, head_length=hl)
+
+ ax.plot(pgrid, g(model, pgrid), 'b-',
+ lw=2, alpha=0.6, label='g')
+ ax.plot(pgrid, pgrid, lw=1, alpha=0.7, label='$45\degree$')
+
+ x = p0
+ xticks = [pmin]
+ xtick_labels = [pmin]
+
+ for i in range(num_arrows):
+ if i == 0:
+ ax.arrow(x, 0.0, 0.0, g(model, x),
+ **arrow_args)
+ else:
+ ax.arrow(x, x, 0.0, g(model, x) - x,
+ **arrow_args)
+ ax.plot((x, x), (0, x), ls='dotted')
+
+ ax.arrow(x, g(model, x),
+ g(model, x) - x, 0, **arrow_args)
+ xticks.append(x)
+ xtick_labels.append(r'$p_{}$'.format(str(i)))
+
+ x = g(model, x)
+ xticks.append(x)
+ xtick_labels.append(r'$p_{}$'.format(str(i+1)))
+ ax.plot((x, x), (0, x), '->', alpha=0.5, color='orange')
+
+ xticks.append(pmax)
+ xtick_labels.append(pmax)
+ ax.set_ylabel(r'$p_{t+1}$')
+ ax.set_xlabel(r'$p_t$')
+ ax.set_xticks(xticks)
+ ax.set_yticks(xticks)
+ ax.set_xticklabels(xtick_labels)
+ ax.set_yticklabels(xtick_labels)
+
+ bbox = (0., 1.04, 1., .104)
+ legend_args = {'bbox_to_anchor': bbox, 'loc': 'upper right'}
+
+ ax.legend(ncol=2, frameon=False, **legend_args, fontsize=14)
+ plt.show()
+```
+
+Now we can set up a market and plot the 45-degree diagram.
+
+```{code-cell} ipython3
+m = Market()
+```
+
+```{code-cell} ipython3
+plot45(m, 0, 9, 2, num_arrows=3)
+```
+
+The plot shows the function $g$ defined in {eq}`def_g` and the 45-degree line.
+
+Think of $ p_t $ as a value on the horizontal axis.
+
+Since $p_{t+1} = g(p_t)$, we use the graph of $g$ to see $p_{t+1}$ on the vertical axis.
+
+Clearly,
+
+- If $ g $ lies above the 45-degree line at $p_t$, then we have $ p_{t+1} > p_t $.
+- If $ g $ lies below the 45-degree line at $p_t$, then we have $ p_{t+1} < p_t $.
+- If $ g $ hits the 45-degree line at $p_t$, then we have $ p_{t+1} = p_t $, so $ p_t $ is a steady state.
+
+Consider the sequence of prices starting at $p_0$, as shown in the figure.
+
+We find $p_1$ on the vertical axis and then shift it to the horizontal axis using the 45-degree line (where values on the two axes are equal).
+
+Then from $p_1$ we obtain $p_2$ and continue.
+
+We can see the start of a cycle.
+
+To confirm this, let's plot a time series.
+
+```{code-cell} ipython3
+def ts_plot_price(model, # Market model
+ p0, # Initial price
+ y_a=3, y_b= 12, # Controls y-axis
+ ts_length=10): # Length of time series
+ """
+ Function to simulate and plot the time series of price.
+
+ """
+ fig, ax = plt.subplots()
+ ax.set_xlabel(r'$t$', fontsize=12)
+ ax.set_ylabel(r'$p_t$', fontsize=12)
+ p = np.empty(ts_length)
+ p[0] = p0
+ for t in range(1, ts_length):
+ p[t] = g(model, p[t-1])
+ ax.plot(np.arange(ts_length),
+ p,
+ 'bo-',
+ alpha=0.6,
+ lw=2,
+ label=r'$p_t$')
+ ax.legend(loc='best', fontsize=10)
+ ax.set_ylim(y_a, y_b)
+ ax.set_xticks(np.arange(ts_length))
+ plt.show()
+```
+
+```{code-cell} ipython3
+ts_plot_price(m, 4, ts_length=15)
+```
+
+We see that a cycle has formed and the cycle is persistent.
+
+(You can confirm this by plotting over a longer time horizon.)
+
+The cycle is "stable", in the sense that prices converge to it from most starting conditions.
+
+For example,
+
+```{code-cell} ipython3
+ts_plot_price(m, 10, ts_length=15)
+```
+
+## Adaptive expectations
+
+Naive expectations are quite simple and also important in driving the cycle that we found.
+
+What if expectations are formed in a different way?
+
+Next we consider adaptive expectations.
+
+This refers to the case where producers form expectations for
+the next period price as a weighted average of their last guess and the
+current spot price.
+
+That is,
+
+```{math}
+:label: pe_adaptive
+p_t^e = \alpha p_{t-1} + (1-\alpha) p^e_{t-1}
+\qquad (0 \leq \alpha \leq 1)
+```
+
+Another way to write this is
+
+```{math}
+:label: pe_adaptive_2
+p_t^e = p^e_{t-1} + \alpha (p_{t-1} - p_{t-1}^e)
+```
+
+This equation helps to show that expectations shift
+
+1. up when prices last period were above expectations
+1. down when prices last period were below expectations
+
+Using {eq}`pe_adaptive`, we obtain the dynamics
+
+$$
+ p_t = - \frac{1}{b} [ S(\alpha p_{t-1} + (1-\alpha) p^e_{t-1}) - a]
+$$
+
+Let's try to simulate the price and observe the dynamics using different values of $\alpha$.
+
+```{code-cell} ipython3
+def find_next_price_adaptive(model, curr_price_exp):
+ """
+ Function to find the next price given the current price expectation
+ and Market model
+ """
+ return - (model.supply(curr_price_exp) - model.a) / model.b
+```
+
+The function below plots price dynamics under adaptive expectations for different values of $\alpha$.
+
+```{code-cell} ipython3
+def ts_price_plot_adaptive(model, p0, ts_length=10, α=[1.0, 0.9, 0.75]):
+ fig, axs = plt.subplots(1, len(α), figsize=(12, 5))
+ for i_plot, a in enumerate(α):
+ pe_last = p0
+ p_values = np.empty(ts_length)
+ p_values[0] = p0
+ for i in range(1, ts_length):
+ p_values[i] = find_next_price_adaptive(model, pe_last)
+ pe_last = a*p_values[i] + (1 - a)*pe_last
+
+ axs[i_plot].plot(np.arange(ts_length), p_values)
+ axs[i_plot].set_title(r'$\alpha={}$'.format(a))
+ axs[i_plot].set_xlabel('t')
+ axs[i_plot].set_ylabel('price')
+ plt.show()
+```
+
+Let's call the function with prices starting at $p_0 = 5$.
+
+```{code-cell} ipython3
+ts_price_plot_adaptive(m, 5, ts_length=30)
+```
+
+Note that if $\alpha=1$, then adaptive expectations are just naive expectation.
+
+Decreasing the value of $\alpha$ shifts more weight to the previous
+expectations, which stabilizes expected prices.
+
+This increased stability can be seen in the figures.
+
+## Exercises
+
+```{exercise-start}
+:label: cobweb_ex1
+```
+Using the default `Market` class and naive expectations, plot a time series simulation of supply (rather than the price).
+
+Show, in particular, that supply also cycles.
+
+```{exercise-end}
+```
+
+```{solution-start} cobweb_ex1
+:class: dropdown
+```
+
+```{code-cell} ipython3
+def ts_plot_supply(model, p0, ts_length=10):
+ """
+ Function to simulate and plot the supply function
+ given the initial price.
+ """
+ pe_last = p0
+ s_values = np.empty(ts_length)
+ for i in range(ts_length):
+ # store quantity
+ s_values[i] = model.supply(pe_last)
+ # update price
+ pe_last = - (s_values[i] - model.a) / model.b
+
+
+ fig, ax = plt.subplots()
+ ax.plot(np.arange(ts_length),
+ s_values,
+ 'bo-',
+ alpha=0.6,
+ lw=2,
+ label=r'supply')
+
+ ax.legend(loc='best', fontsize=10)
+ ax.set_xticks(np.arange(ts_length))
+ ax.set_xlabel("time")
+ ax.set_ylabel("quantity")
+ plt.show()
+```
+
+```{code-cell} ipython3
+m = Market()
+ts_plot_supply(m, 5, 15)
+```
+
+```{solution-end}
+```
+
+```{exercise-start}
+:label: cobweb_ex2
+```
+**Backward looking average expectations**
+
+Backward looking average expectations refers to the case where producers form
+expectations for the next period price as a linear combination of their last
+guess and the second last guess.
+
+That is,
+
+```{math}
+:label: pe_blae
+p_t^e = \alpha p_{t-1} + (1-\alpha) p_{t-2}
+```
+
+
+Simulate and plot the price dynamics for $\alpha \in \{0.1, 0.3, 0.5, 0.8\}$ where $p_0=1$ and $p_1=2.5$.
+
+```{exercise-end}
+```
+
+```{solution-start} cobweb_ex2
+:class: dropdown
+```
+
+```{code-cell} ipython3
+def find_next_price_blae(model, curr_price_exp):
+ """
+ Function to find the next price given the current price expectation
+ and Market model
+ """
+ return - (model.supply(curr_price_exp) - model.a) / model.b
+```
+
+```{code-cell} ipython3
+def ts_plot_price_blae(model, p0, p1, alphas, ts_length=15):
+ """
+ Function to simulate and plot the time series of price
+ using backward looking average expectations.
+ """
+ fig, axes = plt.subplots(len(alphas), 1, figsize=(8, 16))
+
+ for ax, a in zip(axes.flatten(), alphas):
+ p = np.empty(ts_length)
+ p[0] = p0
+ p[1] = p1
+ for t in range(2, ts_length):
+ pe = a*p[t-1] + (1 - a)*p[t-2]
+ p[t] = -(model.supply(pe) - model.a) / model.b
+ ax.plot(np.arange(ts_length),
+ p,
+ 'o-',
+ alpha=0.6,
+ label=r'$\alpha={}$'.format(a))
+ ax.legend(loc='best', fontsize=10)
+ ax.set_xlabel(r'$t$', fontsize=12)
+ ax.set_ylabel(r'$p_t$', fontsize=12)
+ plt.show()
+```
+
+```{code-cell} ipython3
+m = Market()
+ts_plot_price_blae(m,
+ p0=5,
+ p1=6,
+ alphas=[0.1, 0.3, 0.5, 0.8],
+ ts_length=20)
+```
+
+```{solution-end}
+```
\ No newline at end of file
diff --git a/content/lectures/commod_price.ipynb b/book/_build/html/_sources/commod_price.ipynb
similarity index 75%
rename from content/lectures/commod_price.ipynb
rename to book/_build/html/_sources/commod_price.ipynb
index 2fc34ac..2ffa39e 100644
--- a/content/lectures/commod_price.ipynb
+++ b/book/_build/html/_sources/commod_price.ipynb
@@ -2,16 +2,38 @@
"cells": [
{
"cell_type": "markdown",
- "id": "7bb16ff2",
+ "id": "f5bf384a",
"metadata": {},
"source": [
+ "# Commodity Prices\n",
+ "\n",
+ "## Outline\n",
+ "\n",
+ "For more than half of all countries around the globe, [commodities](https://en.wikipedia.org/wiki/Commodity) account for [the majority of total exports](https://unctad.org/publication/commodities-and-development-report-2019).\n",
+ "\n",
+ "Examples of commodities include copper, diamonds, iron ore, lithium, cotton\n",
+ "and coffee beans.\n",
+ "\n",
+ "In this lecture we give an introduction to the theory of commodity prices.\n",
+ "\n",
+ "The lecture is quite advanced relative to other lectures in this series.\n",
+ "\n",
+ "We need to compute an equilibrium, and that equilibrium is described by a\n",
+ "price function.\n",
+ "\n",
+ "We will solve an equation where the price function is the unknown.\n",
+ "\n",
+ "This is harder than solving an equation for an unknown number, or vector.\n",
+ "\n",
+ "The lecture will discuss one way to solve a [functional equation](https://en.wikipedia.org/wiki/Functional_equation) (an equation where the unknown object is a function).\n",
+ "\n",
"For this lecture we need the `yfinance` library."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "305a3ccb",
+ "id": "9282e9a6",
"metadata": {
"tags": [
"hide-output"
@@ -19,23 +41,38 @@
},
"outputs": [],
"source": [
- "%pip install yfinance "
+ "%pip install yfinance"
]
},
{
"cell_type": "markdown",
- "id": "5220e7d9",
+ "id": "d055da4e",
"metadata": {},
"source": [
- "# Commodity Prices\n",
- "\n",
- "For more than half of all countries around the globe, [commodities](https://en.wikipedia.org/wiki/Commodity) account for [the majority of total exports](https://unctad.org/publication/commodities-and-development-report-2019).\n",
- "\n",
- "\n",
- "Examples of commodities include copper, diamonds, iron ore, lithium, cotton\n",
- "and coffee beans.\n",
- "\n",
- "In this lecture we give an introduction to the theory of commodity prices.\n",
+ "We will use the following imports"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e864be1a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import yfinance as yf\n",
+ "import matplotlib.pyplot as plt\n",
+ "from scipy.interpolate import interp1d\n",
+ "from scipy.optimize import brentq\n",
+ "from scipy.stats import beta"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f297f038",
+ "metadata": {},
+ "source": [
+ "## Data\n",
"\n",
"The figure below shows the price of cotton in USD since the start of 2016."
]
@@ -43,7 +80,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "9bdd0c3c",
+ "id": "3b2a6712",
"metadata": {
"tags": [
"hide-input",
@@ -52,15 +89,13 @@
},
"outputs": [],
"source": [
- "import yfinance as yf\n",
- "import matplotlib.pyplot as plt\n",
- "s = yf.download('CT=F', '2016-1-1', '2023-4-1')['Adj Close']"
+ "s = yf.download('CT=F', '2016-1-1', '2023-4-1')['Close']"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "a557e960",
+ "id": "d2cd3321",
"metadata": {
"tags": [
"hide-input"
@@ -71,7 +106,7 @@
"fig, ax = plt.subplots()\n",
"\n",
"ax.plot(s, marker='o', alpha=0.5, ms=1)\n",
- "ax.set_ylabel('price', fontsize=12)\n",
+ "ax.set_ylabel('cotton price in USD', fontsize=12)\n",
"ax.set_xlabel('date', fontsize=12)\n",
"\n",
"plt.show()"
@@ -79,27 +114,34 @@
},
{
"cell_type": "markdown",
- "id": "24e1b6f6",
+ "id": "1bc50faa",
"metadata": {},
"source": [
"The figure shows surprisingly large movements in the price of cotton.\n",
"\n",
- "In general, prices depend on the choices and actions of suppliers, consumers and\n",
- "speculators.\n",
+ "What causes these movements?\n",
+ "\n",
+ "In general, prices depend on the choices and actions of \n",
+ "\n",
+ "1. suppliers, \n",
+ "2. consumers, and\n",
+ "3. speculators.\n",
"\n",
- "Our focus will be on the interaction between these parties, viewed through the\n",
- "lens of the standard competitive storage model \n",
+ "Our focus will be on the interaction between these parties. \n",
+ "\n",
+ "We will connect them together in a dynamic model of supply and demand, called\n",
+ "the *competitive storage model*.\n",
"\n",
"This model was developed by\n",
- "{cite}`samuelson1971stochastic`, \n",
+ "{cite}`samuelson1971stochastic`,\n",
"{cite}`wright1982economic`, {cite}`scheinkman1983simple`,\n",
"{cite}`deaton1992on`, {cite}`deaton1996competitive`, and\n",
"{cite}`chambers1996theory`.\n",
"\n",
"\n",
"\n",
- "## Outline\n",
"\n",
+ "## The competitive storage model\n",
"\n",
"In the competitive storage model, commodities are assets that\n",
"\n",
@@ -114,7 +156,7 @@
"These days, goods such as basic computer chips and integrated circuits are\n",
"often treated as commodities in financial markets, being highly standardized,\n",
"and, for these kinds of commodities, the word \"harvest\" is not\n",
- "appropriate. \n",
+ "appropriate.\n",
"\n",
"Nonetheless, we maintain it for simplicity.\n",
"```\n",
@@ -124,51 +166,27 @@
"It is a function of the current state (which determines\n",
"current harvests and predicts future harvests).\n",
"\n",
- "We begin with the following imports"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "16b0569c",
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import matplotlib.pyplot as plt\n",
- "from numba import jit, vectorize\n",
- "from scipy.interpolate import interp1d\n",
- "from scipy.optimize import minimize_scalar, brentq\n",
- "from scipy.stats import beta"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "21c01171",
- "metadata": {},
- "source": [
- "## The Model\n",
+ "\n",
+ "\n",
+ "## The model\n",
"\n",
"Consider a market for a single commodity, whose price is given at $t$ by\n",
- "$p_t$. \n",
+ "$p_t$.\n",
"\n",
"The harvest of the commodity at time $t$ is $Z_t$.\n",
"\n",
- "We assume that the sequence $\\{ Z_t \\}_{t \\geq 1}$ is IID with common\n",
- "density function $\\phi$. \n",
- "\n",
- "The harvests take values in $S$, a subset of the nonnegative numbers.\n",
+ "We assume that the sequence $\\{ Z_t \\}_{t \\geq 1}$ is IID with common density function $\\phi$, where $\\phi$ is nonnegative.\n",
"\n",
"Speculators can store the commodity between periods, with $I_t$ units\n",
"purchased in the current period yielding $\\alpha I_t$ units in the next.\n",
"\n",
- "Here $\\alpha \\in (0,1)$ is a depreciation rate for the commodity. \n",
+ "Here the parameter $\\alpha \\in (0,1)$ is a depreciation rate for the commodity.\n",
"\n",
"For simplicity, the risk free interest rate is taken to be\n",
- "zero, so expected profit on purchasing $I_t$ units is \n",
+ "zero, so expected profit on purchasing $I_t$ units is\n",
"\n",
"$$\n",
- " \\mathbb{E}_t \\, p_{t+1} \\cdot \\alpha I_t - p_t I_t \n",
+ " \\mathbb{E}_t \\, p_{t+1} \\cdot \\alpha I_t - p_t I_t\n",
" = (\\alpha \\mathbb{E}_t \\, p_{t+1} - p_t) I_t\n",
"$$\n",
"\n",
@@ -187,7 +205,7 @@
"Speculators are assumed to be risk neutral, which means that they buy the\n",
"commodity whenever expected profits are positive.\n",
"\n",
- "As a consequence, if expected prices are positive, then the market is not in\n",
+ "As a consequence, if expected profits are positive, then the market is not in\n",
"equilibrium.\n",
"\n",
"Hence, to be in equilibrium, prices must satisfy the \"no-arbitrage\"\n",
@@ -197,6 +215,7 @@
" \\alpha \\mathbb{E}_t \\, p_{t+1} - p_t \\leq 0\n",
"$$ (eq:arbi)\n",
"\n",
+ "This means that if the expected price is lower than the current price, there is no room for arbitrage.\n",
"\n",
"Profit maximization gives the additional condition\n",
"\n",
@@ -205,7 +224,7 @@
"$$ (eq:pmco)\n",
"\n",
"\n",
- "We also require that the market clears in each period. \n",
+ "We also require that the market clears, with supply equaling demand in each period.\n",
"\n",
"We assume that consumers generate demand quantity $D(p)$ corresponding to\n",
"price $p$.\n",
@@ -215,15 +234,15 @@
"\n",
"Regarding quantities,\n",
"\n",
- "* supply is the sum of carryover by speculators and the current harvest\n",
- "* demand is the sum of purchases by consumers and purchases by speculators. \n",
+ "* supply is the sum of carryover by speculators and the current harvest, and\n",
+ "* demand is the sum of purchases by consumers and purchases by speculators.\n",
"\n",
"Mathematically,\n",
"\n",
- "* supply $ = X_t = \\alpha I_{t-1} + Z_t$ \n",
- "* demand $ = D(p_t) + I_t$ \n",
+ "* supply is given by $X_t = \\alpha I_{t-1} + Z_t$, which takes values in $S := \\mathbb R_+$, while\n",
+ "* demand $ = D(p_t) + I_t$\n",
"\n",
- "Thus, the market equilibrium condition is \n",
+ "Thus, the market equilibrium condition is\n",
"\n",
"$$\n",
" \\alpha I_{t-1} + Z_t = D(p_t) + I_t\n",
@@ -237,14 +256,16 @@
"\n",
"### An equilibrium function\n",
"\n",
- "Now to find an equilibrium? \n",
+ "How can we find an equilibrium?\n",
"\n",
"Our path of attack will be to seek a system of prices that depend only on the\n",
"current state.\n",
"\n",
- "In other words, we take a function $p$ on $S$ and set $p_t = p(X_t)$ for every $t$. \n",
+ "(Our solution method involves using an [ansatz](https://en.wikipedia.org/wiki/Ansatz), which is an educated guess --- in this case for the price function.)\n",
+ "\n",
+ "In other words, we take a function $p$ on $S$ and set $p_t = p(X_t)$ for every $t$.\n",
"\n",
- "Prices and quantities then follow \n",
+ "Prices and quantities then follow\n",
"\n",
"$$\n",
" p_t = p(X_t), \\quad I_t = X_t - D(p_t), \\quad X_{t+1} = \\alpha I_t + Z_{t+1}\n",
@@ -257,11 +278,9 @@
"More precisely, we seek a $p$ such that [](eq:arbi) and [](eq:pmco) hold for\n",
"the corresponding system [](eq:eosy).\n",
"\n",
- "To this end, suppose that there exists a function $p^*$ on $S$\n",
- "satisfying\n",
"\n",
"$$\n",
- " p^*(x) = \\max \n",
+ " p^*(x) = \\max\n",
" \\left\\{\n",
" \\alpha \\int_0^\\infty p^*(\\alpha I(x) + z) \\phi(z)dz, P(x)\n",
" \\right\\}\n",
@@ -276,14 +295,14 @@
"$$ (eq:einvf)\n",
"\n",
"It turns out that such a $p^*$ will suffice, in the sense that [](eq:arbi)\n",
- "and [](eq:pmco) hold for the corresponding system [](eq:eosy). \n",
+ "and [](eq:pmco) hold for the corresponding system [](eq:eosy).\n",
"\n",
- "To see this, observe first that \n",
+ "To see this, observe first that\n",
"\n",
"$$\n",
" \\mathbb{E}_t \\, p_{t+1}\n",
- " = \\mathbb{E}_t \\, p^*(X_{t+1}) \n",
- " = \\mathbb{E}_t \\, p^*(\\alpha I(X_t) + Z_{t+1}) \n",
+ " = \\mathbb{E}_t \\, p^*(X_{t+1})\n",
+ " = \\mathbb{E}_t \\, p^*(\\alpha I(X_t) + Z_{t+1})\n",
" = \\int_0^\\infty p^*(\\alpha I(X_t) + z) \\phi(z)dz\n",
"$$\n",
"\n",
@@ -292,10 +311,10 @@
"$$\n",
" \\alpha \\int_0^\\infty p^*(\\alpha I(X_t) + z) \\phi(z)dz \\leq p^*(X_t)\n",
"$$\n",
- " \n",
- "This inequality is immediate from [](eq:dopf). \n",
"\n",
- "Second, regarding [](eq:pmco), suppose that \n",
+ "This inequality is immediate from [](eq:dopf).\n",
+ "\n",
+ "Second, regarding [](eq:pmco), suppose that\n",
"\n",
"$$\n",
" \\alpha \\int_0^\\infty p^*(\\alpha I(X_t) + z) \\phi(z)dz < p^*(X_t)\n",
@@ -303,11 +322,11 @@
"\n",
"Then by [](eq:dopf) we have $p^*(X_t) = P(X_t)$\n",
"\n",
- "But then $D(p^*(X_t)) = X_t$ and $I_t = I(X_t) = 0$. \n",
+ "But then $D(p^*(X_t)) = X_t$ and $I_t = I(X_t) = 0$.\n",
"\n",
- "As a consequence, both [](eq:arbi) and [](eq:pmco) hold. \n",
+ "As a consequence, both [](eq:arbi) and [](eq:pmco) hold.\n",
"\n",
- "We have found an equilibrium.\n",
+ "We have found an equilibrium, which verifies the ansatz.\n",
"\n",
"\n",
"### Computing the equilibrium\n",
@@ -336,16 +355,16 @@
"This leads us to the update rule\n",
"\n",
"$$\n",
- " p_{k+1}(x) = \\max \n",
+ " p_{k+1}(x) = \\max\n",
" \\left\\{\n",
" \\alpha \\int_0^\\infty p_k(\\alpha ( x - D(p_{k+1}(x))) + z) \\phi(z)dz, P(x)\n",
" \\right\\}\n",
"$$ (eq:dopf2)\n",
"\n",
- "In other words, we take $p_k$ as given and, at each $x$, solve for $q$ in \n",
+ "In other words, we take $p_k$ as given and, at each $x$, solve for $q$ in\n",
"\n",
"$$\n",
- " q = \\max \n",
+ " q = \\max\n",
" \\left\\{\n",
" \\alpha \\int_0^\\infty p_k(\\alpha ( x - D(q)) + z) \\phi(z)dz, P(x)\n",
" \\right\\}\n",
@@ -356,7 +375,7 @@
"\n",
"Then we get the corresponding values $q_1, \\ldots, q_n$.\n",
"\n",
- "Then we compute $p_{k+1}$ as the linear interpolation of \n",
+ "Then we compute $p_{k+1}$ as the linear interpolation of\n",
"the values $q_1, \\ldots, q_n$ over the grid $x_1, \\ldots, x_n$.\n",
"\n",
"Then we repeat, seeking convergence.\n",
@@ -369,17 +388,17 @@
"The distribution $\\phi$ is set to a shifted Beta distribution (although many\n",
"other choices are possible).\n",
"\n",
- "The integral in [](eq:dopf3) is computed via Monte Carlo."
+ "The integral in [](eq:dopf3) is computed via {ref}`Monte Carlo `."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "f7dec601",
+ "id": "8b3999b5",
"metadata": {},
"outputs": [],
"source": [
- "α, a, c = 0.8, 1.0, 2.0 \n",
+ "α, a, c = 0.8, 1.0, 2.0\n",
"beta_a, beta_b = 5, 5\n",
"mc_draw_size = 250\n",
"gridsize = 150\n",
@@ -388,7 +407,7 @@
"\n",
"beta_dist = beta(5, 5)\n",
"Z = a + beta_dist.rvs(mc_draw_size) * c # Shock observations\n",
- "D = P = lambda x: 1.0 / x \n",
+ "D = P = lambda x: 1.0 / x\n",
"tol = 1e-4\n",
"\n",
"\n",
@@ -397,8 +416,8 @@
" new_p = np.empty_like(p_array)\n",
"\n",
" # Interpolate to obtain p as a function.\n",
- " p = interp1d(grid, \n",
- " p_array, \n",
+ " p = interp1d(grid,\n",
+ " p_array,\n",
" fill_value=(p_array[0], p_array[-1]),\n",
" bounds_error=False)\n",
"\n",
@@ -423,14 +442,15 @@
"\n",
"ax.plot(grid, price, 'k-', alpha=0.5, lw=2, label=r'$p^*$')\n",
"ax.legend()\n",
- "ax.set_xlabel('$x$', fontsize=12)\n",
+ "ax.set_xlabel('$x$')\n",
+ "ax.set_ylabel(\"prices\")\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
- "id": "95aaa990",
+ "id": "8899a9b6",
"metadata": {},
"source": [
"The figure above shows the inverse demand curve $P$, which is also $p_0$, as\n",
@@ -443,13 +463,13 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "ab9484f0",
+ "id": "285e9877",
"metadata": {},
"outputs": [],
"source": [
"# Turn the price array into a price function\n",
- "p_star = interp1d(grid, \n",
- " price, \n",
+ "p_star = interp1d(grid,\n",
+ " price,\n",
" fill_value=(price[0], price[-1]),\n",
" bounds_error=False)\n",
"\n",
@@ -473,12 +493,31 @@
}
],
"metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst"
+ }
+ },
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
- }
+ },
+ "source_map": [
+ 10,
+ 39,
+ 42,
+ 47,
+ 54,
+ 60,
+ 66,
+ 76,
+ 352,
+ 401,
+ 410
+ ]
},
"nbformat": 4,
"nbformat_minor": 5
-}
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/commod_price.md b/book/_build/html/_sources/commod_price.md
new file mode 100644
index 0000000..48fb38d
--- /dev/null
+++ b/book/_build/html/_sources/commod_price.md
@@ -0,0 +1,433 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+
+
+
+# Commodity Prices
+
+## Outline
+
+For more than half of all countries around the globe, [commodities](https://en.wikipedia.org/wiki/Commodity) account for [the majority of total exports](https://unctad.org/publication/commodities-and-development-report-2019).
+
+Examples of commodities include copper, diamonds, iron ore, lithium, cotton
+and coffee beans.
+
+In this lecture we give an introduction to the theory of commodity prices.
+
+The lecture is quite advanced relative to other lectures in this series.
+
+We need to compute an equilibrium, and that equilibrium is described by a
+price function.
+
+We will solve an equation where the price function is the unknown.
+
+This is harder than solving an equation for an unknown number, or vector.
+
+The lecture will discuss one way to solve a [functional equation](https://en.wikipedia.org/wiki/Functional_equation) (an equation where the unknown object is a function).
+
+For this lecture we need the `yfinance` library.
+
+```{code-cell} ipython3
+:tags: [hide-output]
+%pip install yfinance
+```
+
+We will use the following imports
+
+
+```{code-cell} ipython3
+import numpy as np
+import yfinance as yf
+import matplotlib.pyplot as plt
+from scipy.interpolate import interp1d
+from scipy.optimize import brentq
+from scipy.stats import beta
+```
+
+## Data
+
+The figure below shows the price of cotton in USD since the start of 2016.
+
+```{code-cell} ipython3
+:tags: [hide-input, hide-output]
+
+s = yf.download('CT=F', '2016-1-1', '2023-4-1')['Close']
+```
+
+```{code-cell} ipython3
+:tags: [hide-input]
+
+fig, ax = plt.subplots()
+
+ax.plot(s, marker='o', alpha=0.5, ms=1)
+ax.set_ylabel('cotton price in USD', fontsize=12)
+ax.set_xlabel('date', fontsize=12)
+
+plt.show()
+```
+
+The figure shows surprisingly large movements in the price of cotton.
+
+What causes these movements?
+
+In general, prices depend on the choices and actions of
+
+1. suppliers,
+2. consumers, and
+3. speculators.
+
+Our focus will be on the interaction between these parties.
+
+We will connect them together in a dynamic model of supply and demand, called
+the *competitive storage model*.
+
+This model was developed by
+{cite}`samuelson1971stochastic`,
+{cite}`wright1982economic`, {cite}`scheinkman1983simple`,
+{cite}`deaton1992on`, {cite}`deaton1996competitive`, and
+{cite}`chambers1996theory`.
+
+
+
+
+## The competitive storage model
+
+In the competitive storage model, commodities are assets that
+
+1. can be traded by speculators and
+1. have intrinsic value to consumers.
+
+Total demand is the sum of consumer demand and demand by speculators.
+
+Supply is exogenous, depending on "harvests".
+
+```{note}
+These days, goods such as basic computer chips and integrated circuits are
+often treated as commodities in financial markets, being highly standardized,
+and, for these kinds of commodities, the word "harvest" is not
+appropriate.
+
+Nonetheless, we maintain it for simplicity.
+```
+
+The equilibrium price is determined competitively.
+
+It is a function of the current state (which determines
+current harvests and predicts future harvests).
+
+
+
+## The model
+
+Consider a market for a single commodity, whose price is given at $t$ by
+$p_t$.
+
+The harvest of the commodity at time $t$ is $Z_t$.
+
+We assume that the sequence $\{ Z_t \}_{t \geq 1}$ is IID with common density function $\phi$, where $\phi$ is nonnegative.
+
+Speculators can store the commodity between periods, with $I_t$ units
+purchased in the current period yielding $\alpha I_t$ units in the next.
+
+Here the parameter $\alpha \in (0,1)$ is a depreciation rate for the commodity.
+
+For simplicity, the risk free interest rate is taken to be
+zero, so expected profit on purchasing $I_t$ units is
+
+$$
+ \mathbb{E}_t \, p_{t+1} \cdot \alpha I_t - p_t I_t
+ = (\alpha \mathbb{E}_t \, p_{t+1} - p_t) I_t
+$$
+
+
+Here $\mathbb{E}_t \, p_{t+1}$ is the expectation of $p_{t+1}$ taken at time
+$t$.
+
+
+
+## Equilibrium
+
+In this section we define the equilibrium and discuss how to compute it.
+
+### Equilibrium conditions
+
+Speculators are assumed to be risk neutral, which means that they buy the
+commodity whenever expected profits are positive.
+
+As a consequence, if expected profits are positive, then the market is not in
+equilibrium.
+
+Hence, to be in equilibrium, prices must satisfy the "no-arbitrage"
+condition
+
+$$
+ \alpha \mathbb{E}_t \, p_{t+1} - p_t \leq 0
+$$ (eq:arbi)
+
+This means that if the expected price is lower than the current price, there is no room for arbitrage.
+
+Profit maximization gives the additional condition
+
+$$
+ \alpha \mathbb{E}_t \, p_{t+1} - p_t < 0 \text{ implies } I_t = 0
+$$ (eq:pmco)
+
+
+We also require that the market clears, with supply equaling demand in each period.
+
+We assume that consumers generate demand quantity $D(p)$ corresponding to
+price $p$.
+
+Let $P := D^{-1}$ be the inverse demand function.
+
+
+Regarding quantities,
+
+* supply is the sum of carryover by speculators and the current harvest, and
+* demand is the sum of purchases by consumers and purchases by speculators.
+
+Mathematically,
+
+* supply is given by $X_t = \alpha I_{t-1} + Z_t$, which takes values in $S := \mathbb R_+$, while
+* demand $ = D(p_t) + I_t$
+
+Thus, the market equilibrium condition is
+
+$$
+ \alpha I_{t-1} + Z_t = D(p_t) + I_t
+$$ (eq:mkeq)
+
+
+The initial condition $X_0 \in S$ is treated as given.
+
+
+
+
+### An equilibrium function
+
+How can we find an equilibrium?
+
+Our path of attack will be to seek a system of prices that depend only on the
+current state.
+
+(Our solution method involves using an [ansatz](https://en.wikipedia.org/wiki/Ansatz), which is an educated guess --- in this case for the price function.)
+
+In other words, we take a function $p$ on $S$ and set $p_t = p(X_t)$ for every $t$.
+
+Prices and quantities then follow
+
+$$
+ p_t = p(X_t), \quad I_t = X_t - D(p_t), \quad X_{t+1} = \alpha I_t + Z_{t+1}
+$$ (eq:eosy)
+
+
+We choose $p$ so that these prices and quantities satisfy the equilibrium
+conditions above.
+
+More precisely, we seek a $p$ such that [](eq:arbi) and [](eq:pmco) hold for
+the corresponding system [](eq:eosy).
+
+
+$$
+ p^*(x) = \max
+ \left\{
+ \alpha \int_0^\infty p^*(\alpha I(x) + z) \phi(z)dz, P(x)
+ \right\}
+ \qquad (x \in S)
+$$ (eq:dopf)
+
+where
+
+$$
+ I(x) := x - D(p^*(x))
+ \qquad (x \in S)
+$$ (eq:einvf)
+
+It turns out that such a $p^*$ will suffice, in the sense that [](eq:arbi)
+and [](eq:pmco) hold for the corresponding system [](eq:eosy).
+
+To see this, observe first that
+
+$$
+ \mathbb{E}_t \, p_{t+1}
+ = \mathbb{E}_t \, p^*(X_{t+1})
+ = \mathbb{E}_t \, p^*(\alpha I(X_t) + Z_{t+1})
+ = \int_0^\infty p^*(\alpha I(X_t) + z) \phi(z)dz
+$$
+
+Thus [](eq:arbi) requires that
+
+$$
+ \alpha \int_0^\infty p^*(\alpha I(X_t) + z) \phi(z)dz \leq p^*(X_t)
+$$
+
+This inequality is immediate from [](eq:dopf).
+
+Second, regarding [](eq:pmco), suppose that
+
+$$
+ \alpha \int_0^\infty p^*(\alpha I(X_t) + z) \phi(z)dz < p^*(X_t)
+$$
+
+Then by [](eq:dopf) we have $p^*(X_t) = P(X_t)$
+
+But then $D(p^*(X_t)) = X_t$ and $I_t = I(X_t) = 0$.
+
+As a consequence, both [](eq:arbi) and [](eq:pmco) hold.
+
+We have found an equilibrium, which verifies the ansatz.
+
+
+### Computing the equilibrium
+
+We now know that an equilibrium can be obtained by finding a function $p^*$
+that satisfies [](eq:dopf).
+
+It can be shown that, under mild conditions there is exactly one function on
+$S$ satisfying [](eq:dopf).
+
+Moreover, we can compute this function using successive approximation.
+
+This means that we start with a guess of the function and then update it using
+[](eq:dopf).
+
+This generates a sequence of functions $p_1, p_2, \ldots$
+
+We continue until this process converges, in the sense that $p_k$ and
+$p_{k+1}$ are very close together.
+
+Then we take the final $p_k$ that we computed as our approximation of $p^*$.
+
+To implement our update step, it is helpful if we put [](eq:dopf) and
+[](eq:einvf) together.
+
+This leads us to the update rule
+
+$$
+ p_{k+1}(x) = \max
+ \left\{
+ \alpha \int_0^\infty p_k(\alpha ( x - D(p_{k+1}(x))) + z) \phi(z)dz, P(x)
+ \right\}
+$$ (eq:dopf2)
+
+In other words, we take $p_k$ as given and, at each $x$, solve for $q$ in
+
+$$
+ q = \max
+ \left\{
+ \alpha \int_0^\infty p_k(\alpha ( x - D(q)) + z) \phi(z)dz, P(x)
+ \right\}
+$$ (eq:dopf3)
+
+Actually we can't do this at every $x$, so instead we do it on a grid of
+points $x_1, \ldots, x_n$.
+
+Then we get the corresponding values $q_1, \ldots, q_n$.
+
+Then we compute $p_{k+1}$ as the linear interpolation of
+the values $q_1, \ldots, q_n$ over the grid $x_1, \ldots, x_n$.
+
+Then we repeat, seeking convergence.
+
+
+## Code
+
+The code below implements this iterative process, starting from $p_0 = P$.
+
+The distribution $\phi$ is set to a shifted Beta distribution (although many
+other choices are possible).
+
+The integral in [](eq:dopf3) is computed via {ref}`Monte Carlo `.
+
+
+```{code-cell} ipython3
+α, a, c = 0.8, 1.0, 2.0
+beta_a, beta_b = 5, 5
+mc_draw_size = 250
+gridsize = 150
+grid_max = 35
+grid = np.linspace(a, grid_max, gridsize)
+
+beta_dist = beta(5, 5)
+Z = a + beta_dist.rvs(mc_draw_size) * c # Shock observations
+D = P = lambda x: 1.0 / x
+tol = 1e-4
+
+
+def T(p_array):
+
+ new_p = np.empty_like(p_array)
+
+ # Interpolate to obtain p as a function.
+ p = interp1d(grid,
+ p_array,
+ fill_value=(p_array[0], p_array[-1]),
+ bounds_error=False)
+
+ # Update
+ for i, x in enumerate(grid):
+
+ h = lambda q: q - max(α * np.mean(p(α * (x - D(q)) + Z)), P(x))
+ new_p[i] = brentq(h, 1e-8, 100)
+
+ return new_p
+
+
+fig, ax = plt.subplots()
+
+price = P(grid)
+ax.plot(grid, price, alpha=0.5, lw=1, label="inverse demand curve")
+error = tol + 1
+while error > tol:
+ new_price = T(price)
+ error = max(np.abs(new_price - price))
+ price = new_price
+
+ax.plot(grid, price, 'k-', alpha=0.5, lw=2, label=r'$p^*$')
+ax.legend()
+ax.set_xlabel('$x$')
+ax.set_ylabel("prices")
+
+plt.show()
+```
+
+The figure above shows the inverse demand curve $P$, which is also $p_0$, as
+well as our approximation of $p^*$.
+
+Once we have an approximation of $p^*$, we can simulate a time series of
+prices.
+
+
+```{code-cell} ipython3
+# Turn the price array into a price function
+p_star = interp1d(grid,
+ price,
+ fill_value=(price[0], price[-1]),
+ bounds_error=False)
+
+def carry_over(x):
+ return α * (x - D(p_star(x)))
+
+def generate_cp_ts(init=1, n=50):
+ X = np.empty(n)
+ X[0] = init
+ for t in range(n-1):
+ Z = a + c * beta_dist.rvs()
+ X[t+1] = carry_over(X[t]) + Z
+ return p_star(X)
+
+fig, ax = plt.subplots()
+ax.plot(generate_cp_ts(), label="price")
+ax.set_xlabel("time")
+ax.legend()
+plt.show()
+```
diff --git a/book/_build/html/_sources/complex_and_trig.ipynb b/book/_build/html/_sources/complex_and_trig.ipynb
new file mode 100644
index 0000000..7fa2620
--- /dev/null
+++ b/book/_build/html/_sources/complex_and_trig.ipynb
@@ -0,0 +1,665 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "283d7118",
+ "metadata": {},
+ "source": [
+ "(complex_and_trig)=\n",
+ "```{raw} html\n",
+ "\n",
+ "```\n",
+ "\n",
+ "```{index} single: python\n",
+ "```\n",
+ "\n",
+ "# Complex Numbers and Trigonometry\n",
+ "\n",
+ "## Overview\n",
+ "\n",
+ "This lecture introduces some elementary mathematics and trigonometry.\n",
+ "\n",
+ "Useful and interesting in its own right, these concepts reap substantial rewards when studying dynamics generated\n",
+ "by linear difference equations or linear differential equations.\n",
+ "\n",
+ "For example, these tools are keys to understanding outcomes attained by Paul\n",
+ "Samuelson (1939) {cite}`Samuelson1939` in his classic paper on interactions\n",
+ "between the investment accelerator and the Keynesian consumption function, our\n",
+ "topic in the lecture {doc}`Samuelson Multiplier Accelerator `.\n",
+ "\n",
+ "In addition to providing foundations for Samuelson's work and extensions of\n",
+ "it, this lecture can be read as a stand-alone quick reminder of key results\n",
+ "from elementary high school trigonometry.\n",
+ "\n",
+ "So let's dive in.\n",
+ "\n",
+ "### Complex Numbers\n",
+ "\n",
+ "A complex number has a **real part** $x$ and a purely **imaginary part** $y$.\n",
+ "\n",
+ "The Euclidean, polar, and trigonometric forms of a complex number $z$ are:\n",
+ "\n",
+ "$$\n",
+ "z = x + iy = re^{i\\theta} = r(\\cos{\\theta} + i \\sin{\\theta})\n",
+ "$$\n",
+ "\n",
+ "The second equality above is known as **Euler's formula**\n",
+ "\n",
+ "- [Euler](https://en.wikipedia.org/wiki/Leonhard_Euler) contributed many other formulas too!\n",
+ "\n",
+ "The complex conjugate $\\bar z$ of $z$ is defined as\n",
+ "\n",
+ "$$\n",
+ "\\bar z = x - iy = r e^{-i \\theta} = r (\\cos{\\theta} - i \\sin{\\theta} )\n",
+ "$$\n",
+ "\n",
+ "The value $x$ is the **real** part of $z$ and $y$ is the\n",
+ "**imaginary** part of $z$.\n",
+ "\n",
+ "The symbol $| z |$ = $\\sqrt{\\bar{z}\\cdot z} = r$ represents the **modulus** of $z$.\n",
+ "\n",
+ "The value $r$ is the Euclidean distance of vector $(x,y)$ from the\n",
+ "origin:\n",
+ "\n",
+ "$$\n",
+ "r = |z| = \\sqrt{x^2 + y^2}\n",
+ "$$\n",
+ "\n",
+ "The value $\\theta$ is the angle of $(x,y)$ with respect to the real axis.\n",
+ "\n",
+ "Evidently, the tangent of $\\theta$ is $\\left(\\frac{y}{x}\\right)$.\n",
+ "\n",
+ "Therefore,\n",
+ "\n",
+ "$$\n",
+ "\\theta = \\tan^{-1} \\Big( \\frac{y}{x} \\Big)\n",
+ "$$\n",
+ "\n",
+ "Three elementary trigonometric functions are\n",
+ "\n",
+ "$$\n",
+ "\\cos{\\theta} = \\frac{x}{r} = \\frac{e^{i\\theta} + e^{-i\\theta}}{2} , \\quad\n",
+ "\\sin{\\theta} = \\frac{y}{r} = \\frac{e^{i\\theta} - e^{-i\\theta}}{2i} , \\quad\n",
+ "\\tan{\\theta} = \\frac{y}{x}\n",
+ "$$\n",
+ "\n",
+ "We'll need the following imports:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8de56cca",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import matplotlib.pyplot as plt\n",
+ "plt.rcParams[\"figure.figsize\"] = (11, 5) #set default figure size\n",
+ "import numpy as np\n",
+ "from sympy import (Symbol, symbols, Eq, nsolve, sqrt, cos, sin, simplify,\n",
+ " init_printing, integrate)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5076b051",
+ "metadata": {},
+ "source": [
+ "### An Example\n",
+ "\n",
+ "```{prf:example}\n",
+ ":label: ct_ex_com\n",
+ "\n",
+ "Consider the complex number $z = 1 + \\sqrt{3} i$.\n",
+ "\n",
+ "For $z = 1 + \\sqrt{3} i$, $x = 1$, $y = \\sqrt{3}$.\n",
+ "\n",
+ "It follows that $r = 2$ and\n",
+ "$\\theta = \\tan^{-1}(\\sqrt{3}) = \\frac{\\pi}{3} = 60^o$.\n",
+ "```\n",
+ "\n",
+ "Let's use Python to plot the trigonometric form of the complex number\n",
+ "$z = 1 + \\sqrt{3} i$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c67cb2a4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Abbreviate useful values and functions\n",
+ "π = np.pi\n",
+ "\n",
+ "\n",
+ "# Set parameters\n",
+ "r = 2\n",
+ "θ = π/3\n",
+ "x = r * np.cos(θ)\n",
+ "x_range = np.linspace(0, x, 1000)\n",
+ "θ_range = np.linspace(0, θ, 1000)\n",
+ "\n",
+ "# Plot\n",
+ "fig = plt.figure(figsize=(8, 8))\n",
+ "ax = plt.subplot(111, projection='polar')\n",
+ "\n",
+ "ax.plot((0, θ), (0, r), marker='o', color='b') # Plot r\n",
+ "ax.plot(np.zeros(x_range.shape), x_range, color='b') # Plot x\n",
+ "ax.plot(θ_range, x / np.cos(θ_range), color='b') # Plot y\n",
+ "ax.plot(θ_range, np.full(θ_range.shape, 0.1), color='r') # Plot θ\n",
+ "\n",
+ "ax.margins(0) # Let the plot starts at origin\n",
+ "\n",
+ "ax.set_title(\"Trigonometry of complex numbers\", va='bottom',\n",
+ " fontsize='x-large')\n",
+ "\n",
+ "ax.set_rmax(2)\n",
+ "ax.set_rticks((0.5, 1, 1.5, 2)) # Less radial ticks\n",
+ "ax.set_rlabel_position(-88.5) # Get radial labels away from plotted line\n",
+ "\n",
+ "ax.text(θ, r+0.01 , r'$z = x + iy = 1 + \\sqrt{3}\\, i$') # Label z\n",
+ "ax.text(θ+0.2, 1 , '$r = 2$') # Label r\n",
+ "ax.text(0-0.2, 0.5, '$x = 1$') # Label x\n",
+ "ax.text(0.5, 1.2, r'$y = \\sqrt{3}$') # Label y\n",
+ "ax.text(0.25, 0.15, r'$\\theta = 60^o$') # Label θ\n",
+ "\n",
+ "ax.grid(True)\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8a5dd8c8",
+ "metadata": {},
+ "source": [
+ "## De Moivre's Theorem\n",
+ "\n",
+ "de Moivre's theorem states that:\n",
+ "\n",
+ "$$\n",
+ "(r(\\cos{\\theta} + i \\sin{\\theta}))^n =\n",
+ "r^n e^{in\\theta} =\n",
+ "r^n(\\cos{n\\theta} + i \\sin{n\\theta})\n",
+ "$$\n",
+ "\n",
+ "To prove de Moivre's theorem, note that\n",
+ "\n",
+ "$$\n",
+ "(r(\\cos{\\theta} + i \\sin{\\theta}))^n = \\big( re^{i\\theta} \\big)^n\n",
+ "$$\n",
+ "\n",
+ "and compute.\n",
+ "\n",
+ "## Applications of de Moivre's Theorem\n",
+ "\n",
+ "### Example 1\n",
+ "\n",
+ "We can use de Moivre's theorem to show that\n",
+ "$r = \\sqrt{x^2 + y^2}$.\n",
+ "\n",
+ "We have\n",
+ "\n",
+ "$$\n",
+ "\\begin{aligned}\n",
+ "1 &= e^{i\\theta} e^{-i\\theta} \\\\\n",
+ "&= (\\cos{\\theta} + i \\sin{\\theta})(\\cos{(\\text{-}\\theta)} + i \\sin{(\\text{-}\\theta)}) \\\\\n",
+ "&= (\\cos{\\theta} + i \\sin{\\theta})(\\cos{\\theta} - i \\sin{\\theta}) \\\\\n",
+ "&= \\cos^2{\\theta} + \\sin^2{\\theta} \\\\\n",
+ "&= \\frac{x^2}{r^2} + \\frac{y^2}{r^2}\n",
+ "\\end{aligned}\n",
+ "$$\n",
+ "\n",
+ "and thus\n",
+ "\n",
+ "$$\n",
+ "x^2 + y^2 = r^2\n",
+ "$$\n",
+ "\n",
+ "We recognize this as a theorem of **Pythagoras**.\n",
+ "\n",
+ "### Example 2\n",
+ "\n",
+ "Let $z = re^{i\\theta}$ and $\\bar{z} = re^{-i\\theta}$ so that $\\bar{z}$ is the **complex conjugate** of $z$.\n",
+ "\n",
+ "$(z, \\bar z)$ form a **complex conjugate pair** of complex numbers.\n",
+ "\n",
+ "Let $a = pe^{i\\omega}$ and $\\bar{a} = pe^{-i\\omega}$ be\n",
+ "another complex conjugate pair.\n",
+ "\n",
+ "For each element of a sequence of integers $n = 0, 1, 2, \\ldots, $.\n",
+ "\n",
+ "To do so, we can apply de Moivre's formula.\n",
+ "\n",
+ "Thus,\n",
+ "\n",
+ "$$\n",
+ "\\begin{aligned}\n",
+ "x_n &= az^n + \\bar{a}\\bar{z}^n \\\\\n",
+ "&= p e^{i\\omega} (re^{i\\theta})^n + p e^{-i\\omega} (re^{-i\\theta})^n \\\\\n",
+ "&= pr^n e^{i (\\omega + n\\theta)} + pr^n e^{-i (\\omega + n\\theta)} \\\\\n",
+ "&= pr^n [\\cos{(\\omega + n\\theta)} + i \\sin{(\\omega + n\\theta)} +\n",
+ " \\cos{(\\omega + n\\theta)} - i \\sin{(\\omega + n\\theta)}] \\\\\n",
+ "&= 2 pr^n \\cos{(\\omega + n\\theta)}\n",
+ "\\end{aligned}\n",
+ "$$\n",
+ "\n",
+ "### Example 3\n",
+ "\n",
+ "This example provides machinery that is at the heard of Samuelson's analysis of his multiplier-accelerator model {cite}`Samuelson1939`.\n",
+ "\n",
+ "Thus, consider a **second-order linear difference equation**\n",
+ "\n",
+ "$$\n",
+ "x_{n+2} = c_1 x_{n+1} + c_2 x_n\n",
+ "$$\n",
+ "\n",
+ "whose **characteristic polynomial** is\n",
+ "\n",
+ "$$\n",
+ "z^2 - c_1 z - c_2 = 0\n",
+ "$$\n",
+ "\n",
+ "or\n",
+ "\n",
+ "$$\n",
+ "(z^2 - c_1 z - c_2 ) = (z - z_1)(z- z_2) = 0\n",
+ "$$\n",
+ "\n",
+ "has roots $z_1, z_1$.\n",
+ "\n",
+ "A **solution** is a sequence $\\{x_n\\}_{n=0}^\\infty$ that satisfies\n",
+ "the difference equation.\n",
+ "\n",
+ "Under the following circumstances, we can apply our example 2 formula to\n",
+ "solve the difference equation\n",
+ "\n",
+ "- the roots $z_1, z_2$ of the characteristic polynomial of the\n",
+ " difference equation form a complex conjugate pair\n",
+ "- the values $x_0, x_1$ are given initial conditions\n",
+ "\n",
+ "To solve the difference equation, recall from example 2 that\n",
+ "\n",
+ "$$\n",
+ "x_n = 2 pr^n \\cos{(\\omega + n\\theta)}\n",
+ "$$\n",
+ "\n",
+ "where $\\omega, p$ are coefficients to be determined from\n",
+ "information encoded in the initial conditions $x_1, x_0$.\n",
+ "\n",
+ "Since\n",
+ "$x_0 = 2 p \\cos{\\omega}$ and $x_1 = 2 pr \\cos{(\\omega + \\theta)}$\n",
+ "the ratio of $x_1$ to $x_0$ is\n",
+ "\n",
+ "$$\n",
+ "\\frac{x_1}{x_0} = \\frac{r \\cos{(\\omega + \\theta)}}{\\cos{\\omega}}\n",
+ "$$\n",
+ "\n",
+ "We can solve this equation for $\\omega$ then solve for $p$ using $x_0 = 2 pr^0 \\cos{(\\omega + n\\theta)}$.\n",
+ "\n",
+ "With the `sympy` package in Python, we are able to solve and plot the\n",
+ "dynamics of $x_n$ given different values of $n$.\n",
+ "\n",
+ "In this example, we set the initial values: - $r = 0.9$ -\n",
+ "$\\theta = \\frac{1}{4}\\pi$ - $x_0 = 4$ -\n",
+ "$x_1 = r \\cdot 2\\sqrt{2} = 1.8 \\sqrt{2}$.\n",
+ "\n",
+ "We first numerically solve for $\\omega$ and $p$ using\n",
+ "`nsolve` in the `sympy` package based on the above initial\n",
+ "condition:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "43825cc5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Set parameters\n",
+ "r = 0.9\n",
+ "θ = π/4\n",
+ "x0 = 4\n",
+ "x1 = 2 * r * sqrt(2)\n",
+ "\n",
+ "# Define symbols to be calculated\n",
+ "ω, p = symbols('ω p', real=True)\n",
+ "\n",
+ "# Solve for ω\n",
+ "## Note: we choose the solution near 0\n",
+ "eq1 = Eq(x1/x0 - r * cos(ω+θ) / cos(ω), 0)\n",
+ "ω = nsolve(eq1, ω, 0)\n",
+ "ω = float(ω)\n",
+ "print(f'ω = {ω:1.3f}')\n",
+ "\n",
+ "# Solve for p\n",
+ "eq2 = Eq(x0 - 2 * p * cos(ω), 0)\n",
+ "p = nsolve(eq2, p, 0)\n",
+ "p = float(p)\n",
+ "print(f'p = {p:1.3f}')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "85f4ff89",
+ "metadata": {},
+ "source": [
+ "Using the code above, we compute that\n",
+ "$\\omega = 0$ and $p = 2$.\n",
+ "\n",
+ "Then we plug in the values we solve for $\\omega$ and $p$\n",
+ "and plot the dynamic."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a3b313d3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Define range of n\n",
+ "max_n = 30\n",
+ "n = np.arange(0, max_n+1, 0.01)\n",
+ "\n",
+ "# Define x_n\n",
+ "x = lambda n: 2 * p * r**n * np.cos(ω + n * θ)\n",
+ "\n",
+ "# Plot\n",
+ "fig, ax = plt.subplots(figsize=(12, 8))\n",
+ "\n",
+ "ax.plot(n, x(n))\n",
+ "ax.set(xlim=(0, max_n), ylim=(-5, 5), xlabel='$n$', ylabel='$x_n$')\n",
+ "\n",
+ "# Set x-axis in the middle of the plot\n",
+ "ax.spines['bottom'].set_position('center')\n",
+ "ax.spines['right'].set_color('none')\n",
+ "ax.spines['top'].set_color('none')\n",
+ "ax.xaxis.set_ticks_position('bottom')\n",
+ "ax.yaxis.set_ticks_position('left')\n",
+ "\n",
+ "ticklab = ax.xaxis.get_ticklabels()[0] # Set x-label position\n",
+ "trans = ticklab.get_transform()\n",
+ "ax.xaxis.set_label_coords(31, 0, transform=trans)\n",
+ "\n",
+ "ticklab = ax.yaxis.get_ticklabels()[0] # Set y-label position\n",
+ "trans = ticklab.get_transform()\n",
+ "ax.yaxis.set_label_coords(0, 5, transform=trans)\n",
+ "\n",
+ "ax.grid()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b8c9bcd8",
+ "metadata": {},
+ "source": [
+ "### Trigonometric Identities\n",
+ "\n",
+ "We can obtain a complete suite of trigonometric identities by\n",
+ "appropriately manipulating polar forms of complex numbers.\n",
+ "\n",
+ "We'll get many of them by deducing implications of the equality\n",
+ "\n",
+ "$$\n",
+ "e^{i(\\omega + \\theta)} = e^{i\\omega} e^{i\\theta}\n",
+ "$$\n",
+ "\n",
+ "For example, we'll calculate identities for\n",
+ "\n",
+ "$\\cos{(\\omega + \\theta)}$ and $\\sin{(\\omega + \\theta)}$.\n",
+ "\n",
+ "Using the sine and cosine formulas presented at the beginning of this\n",
+ "lecture, we have:\n",
+ "\n",
+ "$$\n",
+ "\\begin{aligned}\n",
+ "\\cos{(\\omega + \\theta)} = \\frac{e^{i(\\omega + \\theta)} + e^{-i(\\omega + \\theta)}}{2} \\\\\n",
+ "\\sin{(\\omega + \\theta)} = \\frac{e^{i(\\omega + \\theta)} - e^{-i(\\omega + \\theta)}}{2i}\n",
+ "\\end{aligned}\n",
+ "$$\n",
+ "\n",
+ "We can also obtain the trigonometric identities as follows:\n",
+ "\n",
+ "$$\n",
+ "\\begin{aligned}\n",
+ "\\cos{(\\omega + \\theta)} + i \\sin{(\\omega + \\theta)}\n",
+ "&= e^{i(\\omega + \\theta)} \\\\\n",
+ "&= e^{i\\omega} e^{i\\theta} \\\\\n",
+ "&= (\\cos{\\omega} + i \\sin{\\omega})(\\cos{\\theta} + i \\sin{\\theta}) \\\\\n",
+ "&= (\\cos{\\omega}\\cos{\\theta} - \\sin{\\omega}\\sin{\\theta}) +\n",
+ "i (\\cos{\\omega}\\sin{\\theta} + \\sin{\\omega}\\cos{\\theta})\n",
+ "\\end{aligned}\n",
+ "$$\n",
+ "\n",
+ "Since both real and imaginary parts of the above formula should be\n",
+ "equal, we get:\n",
+ "\n",
+ "$$\n",
+ "\\begin{aligned}\n",
+ "\\cos{(\\omega + \\theta)} = \\cos{\\omega}\\cos{\\theta} - \\sin{\\omega}\\sin{\\theta} \\\\\n",
+ "\\sin{(\\omega + \\theta)} = \\cos{\\omega}\\sin{\\theta} + \\sin{\\omega}\\cos{\\theta}\n",
+ "\\end{aligned}\n",
+ "$$\n",
+ "\n",
+ "The equations above are also known as the **angle sum identities**. We\n",
+ "can verify the equations using the `simplify` function in the\n",
+ "`sympy` package:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f5f63e9f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Define symbols\n",
+ "ω, θ = symbols('ω θ', real=True)\n",
+ "\n",
+ "# Verify\n",
+ "print(\"cos(ω)cos(θ) - sin(ω)sin(θ) =\",\n",
+ " simplify(cos(ω)*cos(θ) - sin(ω) * sin(θ)))\n",
+ "print(\"cos(ω)sin(θ) + sin(ω)cos(θ) =\",\n",
+ " simplify(cos(ω)*sin(θ) + sin(ω) * cos(θ)))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "dc86dcb1",
+ "metadata": {},
+ "source": [
+ "### Trigonometric Integrals\n",
+ "\n",
+ "We can also compute the trigonometric integrals using polar forms of\n",
+ "complex numbers.\n",
+ "\n",
+ "For example, we want to solve the following integral:\n",
+ "\n",
+ "$$\n",
+ "\\int_{-\\pi}^{\\pi} \\cos(\\omega) \\sin(\\omega) \\, d\\omega\n",
+ "$$\n",
+ "\n",
+ "Using Euler's formula, we have:\n",
+ "\n",
+ "$$\n",
+ "\\begin{aligned}\n",
+ "\\int \\cos(\\omega) \\sin(\\omega) \\, d\\omega\n",
+ "&=\n",
+ "\\int\n",
+ "\\frac{(e^{i\\omega} + e^{-i\\omega})}{2}\n",
+ "\\frac{(e^{i\\omega} - e^{-i\\omega})}{2i}\n",
+ "\\, d\\omega \\\\\n",
+ "&=\n",
+ "\\frac{1}{4i}\n",
+ "\\int\n",
+ "e^{2i\\omega} - e^{-2i\\omega}\n",
+ "\\, d\\omega \\\\\n",
+ "&=\n",
+ "\\frac{1}{4i}\n",
+ "\\bigg( \\frac{-i}{2} e^{2i\\omega} - \\frac{i}{2} e^{-2i\\omega} + C_1 \\bigg) \\\\\n",
+ "&=\n",
+ "-\\frac{1}{8}\n",
+ "\\bigg[ \\bigg(e^{i\\omega}\\bigg)^2 + \\bigg(e^{-i\\omega}\\bigg)^2 - 2 \\bigg] + C_2 \\\\\n",
+ "&=\n",
+ "-\\frac{1}{8} (e^{i\\omega} - e^{-i\\omega})^2 + C_2 \\\\\n",
+ "&=\n",
+ "\\frac{1}{2} \\bigg( \\frac{e^{i\\omega} - e^{-i\\omega}}{2i} \\bigg)^2 + C_2 \\\\\n",
+ "&= \\frac{1}{2} \\sin^2(\\omega) + C_2\n",
+ "\\end{aligned}\n",
+ "$$\n",
+ "\n",
+ "and thus:\n",
+ "\n",
+ "$$\n",
+ "\\int_{-\\pi}^{\\pi} \\cos(\\omega) \\sin(\\omega) \\, d\\omega =\n",
+ "\\frac{1}{2}\\sin^2(\\pi) - \\frac{1}{2}\\sin^2(-\\pi) = 0\n",
+ "$$\n",
+ "\n",
+ "We can verify the analytical as well as numerical results using\n",
+ "`integrate` in the `sympy` package:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5811b36b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Set initial printing\n",
+ "init_printing(use_latex=\"mathjax\")\n",
+ "\n",
+ "ω = Symbol('ω')\n",
+ "print('The analytical solution for integral of cos(ω)sin(ω) is:')\n",
+ "integrate(cos(ω) * sin(ω), ω)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c6993839",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print('The numerical solution for the integral of cos(ω)sin(ω) \\\n",
+ "from -π to π is:')\n",
+ "integrate(cos(ω) * sin(ω), (ω, -π, π))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "57386dbe",
+ "metadata": {},
+ "source": [
+ "### Exercises\n",
+ "\n",
+ "```{exercise}\n",
+ ":label: complex_ex1\n",
+ "\n",
+ "We invite the reader to verify analytically and with the `sympy` package the following two equalities:\n",
+ "\n",
+ "$$\n",
+ "\\int_{-\\pi}^{\\pi} \\cos (\\omega)^2 \\, d\\omega = \\pi\n",
+ "$$\n",
+ "\n",
+ "$$\n",
+ "\\int_{-\\pi}^{\\pi} \\sin (\\omega)^2 \\, d\\omega = \\pi\n",
+ "$$\n",
+ "```\n",
+ "\n",
+ "```{solution-start} complex_ex1\n",
+ ":class: dropdown\n",
+ "```\n",
+ "\n",
+ "Let's import symbolic $\\pi$ from `sympy`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "29590374",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Import symbolic π from sympy\n",
+ "from sympy import pi"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2d8629e8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print('The analytical solution for the integral of cos(ω)**2 \\\n",
+ "from -π to π is:')\n",
+ "\n",
+ "integrate(cos(ω)**2, (ω, -pi, pi))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "00bedf44",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print('The analytical solution for the integral of sin(ω)**2 \\\n",
+ "from -π to π is:')\n",
+ "\n",
+ "integrate(sin(ω)**2, (ω, -pi, pi))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "62fd0934",
+ "metadata": {},
+ "source": [
+ "```{solution-end}\n",
+ "```"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst"
+ }
+ },
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "source_map": [
+ 10,
+ 96,
+ 102,
+ 120,
+ 158,
+ 295,
+ 317,
+ 325,
+ 356,
+ 410,
+ 419,
+ 471,
+ 480,
+ 484,
+ 508,
+ 513,
+ 520,
+ 525
+ ]
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/complex_and_trig.md b/book/_build/html/_sources/complex_and_trig.md
new file mode 100644
index 0000000..7f40497
--- /dev/null
+++ b/book/_build/html/_sources/complex_and_trig.md
@@ -0,0 +1,528 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+kernelspec:
+ display_name: Python 3
+ language: python
+ name: python3
+---
+
+(complex_and_trig)=
+```{raw} html
+
+```
+
+```{index} single: python
+```
+
+# Complex Numbers and Trigonometry
+
+## Overview
+
+This lecture introduces some elementary mathematics and trigonometry.
+
+Useful and interesting in its own right, these concepts reap substantial rewards when studying dynamics generated
+by linear difference equations or linear differential equations.
+
+For example, these tools are keys to understanding outcomes attained by Paul
+Samuelson (1939) {cite}`Samuelson1939` in his classic paper on interactions
+between the investment accelerator and the Keynesian consumption function, our
+topic in the lecture {doc}`Samuelson Multiplier Accelerator `.
+
+In addition to providing foundations for Samuelson's work and extensions of
+it, this lecture can be read as a stand-alone quick reminder of key results
+from elementary high school trigonometry.
+
+So let's dive in.
+
+### Complex Numbers
+
+A complex number has a **real part** $x$ and a purely **imaginary part** $y$.
+
+The Euclidean, polar, and trigonometric forms of a complex number $z$ are:
+
+$$
+z = x + iy = re^{i\theta} = r(\cos{\theta} + i \sin{\theta})
+$$
+
+The second equality above is known as **Euler's formula**
+
+- [Euler](https://en.wikipedia.org/wiki/Leonhard_Euler) contributed many other formulas too!
+
+The complex conjugate $\bar z$ of $z$ is defined as
+
+$$
+\bar z = x - iy = r e^{-i \theta} = r (\cos{\theta} - i \sin{\theta} )
+$$
+
+The value $x$ is the **real** part of $z$ and $y$ is the
+**imaginary** part of $z$.
+
+The symbol $| z |$ = $\sqrt{\bar{z}\cdot z} = r$ represents the **modulus** of $z$.
+
+The value $r$ is the Euclidean distance of vector $(x,y)$ from the
+origin:
+
+$$
+r = |z| = \sqrt{x^2 + y^2}
+$$
+
+The value $\theta$ is the angle of $(x,y)$ with respect to the real axis.
+
+Evidently, the tangent of $\theta$ is $\left(\frac{y}{x}\right)$.
+
+Therefore,
+
+$$
+\theta = \tan^{-1} \Big( \frac{y}{x} \Big)
+$$
+
+Three elementary trigonometric functions are
+
+$$
+\cos{\theta} = \frac{x}{r} = \frac{e^{i\theta} + e^{-i\theta}}{2} , \quad
+\sin{\theta} = \frac{y}{r} = \frac{e^{i\theta} - e^{-i\theta}}{2i} , \quad
+\tan{\theta} = \frac{y}{x}
+$$
+
+We'll need the following imports:
+
+```{code-cell} ipython
+import matplotlib.pyplot as plt
+plt.rcParams["figure.figsize"] = (11, 5) #set default figure size
+import numpy as np
+from sympy import (Symbol, symbols, Eq, nsolve, sqrt, cos, sin, simplify,
+ init_printing, integrate)
+```
+
+### An Example
+
+```{prf:example}
+:label: ct_ex_com
+
+Consider the complex number $z = 1 + \sqrt{3} i$.
+
+For $z = 1 + \sqrt{3} i$, $x = 1$, $y = \sqrt{3}$.
+
+It follows that $r = 2$ and
+$\theta = \tan^{-1}(\sqrt{3}) = \frac{\pi}{3} = 60^o$.
+```
+
+Let's use Python to plot the trigonometric form of the complex number
+$z = 1 + \sqrt{3} i$.
+
+```{code-cell} python3
+# Abbreviate useful values and functions
+π = np.pi
+
+
+# Set parameters
+r = 2
+θ = π/3
+x = r * np.cos(θ)
+x_range = np.linspace(0, x, 1000)
+θ_range = np.linspace(0, θ, 1000)
+
+# Plot
+fig = plt.figure(figsize=(8, 8))
+ax = plt.subplot(111, projection='polar')
+
+ax.plot((0, θ), (0, r), marker='o', color='b') # Plot r
+ax.plot(np.zeros(x_range.shape), x_range, color='b') # Plot x
+ax.plot(θ_range, x / np.cos(θ_range), color='b') # Plot y
+ax.plot(θ_range, np.full(θ_range.shape, 0.1), color='r') # Plot θ
+
+ax.margins(0) # Let the plot starts at origin
+
+ax.set_title("Trigonometry of complex numbers", va='bottom',
+ fontsize='x-large')
+
+ax.set_rmax(2)
+ax.set_rticks((0.5, 1, 1.5, 2)) # Less radial ticks
+ax.set_rlabel_position(-88.5) # Get radial labels away from plotted line
+
+ax.text(θ, r+0.01 , r'$z = x + iy = 1 + \sqrt{3}\, i$') # Label z
+ax.text(θ+0.2, 1 , '$r = 2$') # Label r
+ax.text(0-0.2, 0.5, '$x = 1$') # Label x
+ax.text(0.5, 1.2, r'$y = \sqrt{3}$') # Label y
+ax.text(0.25, 0.15, r'$\theta = 60^o$') # Label θ
+
+ax.grid(True)
+plt.show()
+```
+
+## De Moivre's Theorem
+
+de Moivre's theorem states that:
+
+$$
+(r(\cos{\theta} + i \sin{\theta}))^n =
+r^n e^{in\theta} =
+r^n(\cos{n\theta} + i \sin{n\theta})
+$$
+
+To prove de Moivre's theorem, note that
+
+$$
+(r(\cos{\theta} + i \sin{\theta}))^n = \big( re^{i\theta} \big)^n
+$$
+
+and compute.
+
+## Applications of de Moivre's Theorem
+
+### Example 1
+
+We can use de Moivre's theorem to show that
+$r = \sqrt{x^2 + y^2}$.
+
+We have
+
+$$
+\begin{aligned}
+1 &= e^{i\theta} e^{-i\theta} \\
+&= (\cos{\theta} + i \sin{\theta})(\cos{(\text{-}\theta)} + i \sin{(\text{-}\theta)}) \\
+&= (\cos{\theta} + i \sin{\theta})(\cos{\theta} - i \sin{\theta}) \\
+&= \cos^2{\theta} + \sin^2{\theta} \\
+&= \frac{x^2}{r^2} + \frac{y^2}{r^2}
+\end{aligned}
+$$
+
+and thus
+
+$$
+x^2 + y^2 = r^2
+$$
+
+We recognize this as a theorem of **Pythagoras**.
+
+### Example 2
+
+Let $z = re^{i\theta}$ and $\bar{z} = re^{-i\theta}$ so that $\bar{z}$ is the **complex conjugate** of $z$.
+
+$(z, \bar z)$ form a **complex conjugate pair** of complex numbers.
+
+Let $a = pe^{i\omega}$ and $\bar{a} = pe^{-i\omega}$ be
+another complex conjugate pair.
+
+For each element of a sequence of integers $n = 0, 1, 2, \ldots, $.
+
+To do so, we can apply de Moivre's formula.
+
+Thus,
+
+$$
+\begin{aligned}
+x_n &= az^n + \bar{a}\bar{z}^n \\
+&= p e^{i\omega} (re^{i\theta})^n + p e^{-i\omega} (re^{-i\theta})^n \\
+&= pr^n e^{i (\omega + n\theta)} + pr^n e^{-i (\omega + n\theta)} \\
+&= pr^n [\cos{(\omega + n\theta)} + i \sin{(\omega + n\theta)} +
+ \cos{(\omega + n\theta)} - i \sin{(\omega + n\theta)}] \\
+&= 2 pr^n \cos{(\omega + n\theta)}
+\end{aligned}
+$$
+
+### Example 3
+
+This example provides machinery that is at the heard of Samuelson's analysis of his multiplier-accelerator model {cite}`Samuelson1939`.
+
+Thus, consider a **second-order linear difference equation**
+
+$$
+x_{n+2} = c_1 x_{n+1} + c_2 x_n
+$$
+
+whose **characteristic polynomial** is
+
+$$
+z^2 - c_1 z - c_2 = 0
+$$
+
+or
+
+$$
+(z^2 - c_1 z - c_2 ) = (z - z_1)(z- z_2) = 0
+$$
+
+has roots $z_1, z_1$.
+
+A **solution** is a sequence $\{x_n\}_{n=0}^\infty$ that satisfies
+the difference equation.
+
+Under the following circumstances, we can apply our example 2 formula to
+solve the difference equation
+
+- the roots $z_1, z_2$ of the characteristic polynomial of the
+ difference equation form a complex conjugate pair
+- the values $x_0, x_1$ are given initial conditions
+
+To solve the difference equation, recall from example 2 that
+
+$$
+x_n = 2 pr^n \cos{(\omega + n\theta)}
+$$
+
+where $\omega, p$ are coefficients to be determined from
+information encoded in the initial conditions $x_1, x_0$.
+
+Since
+$x_0 = 2 p \cos{\omega}$ and $x_1 = 2 pr \cos{(\omega + \theta)}$
+the ratio of $x_1$ to $x_0$ is
+
+$$
+\frac{x_1}{x_0} = \frac{r \cos{(\omega + \theta)}}{\cos{\omega}}
+$$
+
+We can solve this equation for $\omega$ then solve for $p$ using $x_0 = 2 pr^0 \cos{(\omega + n\theta)}$.
+
+With the `sympy` package in Python, we are able to solve and plot the
+dynamics of $x_n$ given different values of $n$.
+
+In this example, we set the initial values: - $r = 0.9$ -
+$\theta = \frac{1}{4}\pi$ - $x_0 = 4$ -
+$x_1 = r \cdot 2\sqrt{2} = 1.8 \sqrt{2}$.
+
+We first numerically solve for $\omega$ and $p$ using
+`nsolve` in the `sympy` package based on the above initial
+condition:
+
+```{code-cell} python3
+# Set parameters
+r = 0.9
+θ = π/4
+x0 = 4
+x1 = 2 * r * sqrt(2)
+
+# Define symbols to be calculated
+ω, p = symbols('ω p', real=True)
+
+# Solve for ω
+## Note: we choose the solution near 0
+eq1 = Eq(x1/x0 - r * cos(ω+θ) / cos(ω), 0)
+ω = nsolve(eq1, ω, 0)
+ω = float(ω)
+print(f'ω = {ω:1.3f}')
+
+# Solve for p
+eq2 = Eq(x0 - 2 * p * cos(ω), 0)
+p = nsolve(eq2, p, 0)
+p = float(p)
+print(f'p = {p:1.3f}')
+```
+
+Using the code above, we compute that
+$\omega = 0$ and $p = 2$.
+
+Then we plug in the values we solve for $\omega$ and $p$
+and plot the dynamic.
+
+```{code-cell} python3
+# Define range of n
+max_n = 30
+n = np.arange(0, max_n+1, 0.01)
+
+# Define x_n
+x = lambda n: 2 * p * r**n * np.cos(ω + n * θ)
+
+# Plot
+fig, ax = plt.subplots(figsize=(12, 8))
+
+ax.plot(n, x(n))
+ax.set(xlim=(0, max_n), ylim=(-5, 5), xlabel='$n$', ylabel='$x_n$')
+
+# Set x-axis in the middle of the plot
+ax.spines['bottom'].set_position('center')
+ax.spines['right'].set_color('none')
+ax.spines['top'].set_color('none')
+ax.xaxis.set_ticks_position('bottom')
+ax.yaxis.set_ticks_position('left')
+
+ticklab = ax.xaxis.get_ticklabels()[0] # Set x-label position
+trans = ticklab.get_transform()
+ax.xaxis.set_label_coords(31, 0, transform=trans)
+
+ticklab = ax.yaxis.get_ticklabels()[0] # Set y-label position
+trans = ticklab.get_transform()
+ax.yaxis.set_label_coords(0, 5, transform=trans)
+
+ax.grid()
+plt.show()
+```
+
+### Trigonometric Identities
+
+We can obtain a complete suite of trigonometric identities by
+appropriately manipulating polar forms of complex numbers.
+
+We'll get many of them by deducing implications of the equality
+
+$$
+e^{i(\omega + \theta)} = e^{i\omega} e^{i\theta}
+$$
+
+For example, we'll calculate identities for
+
+$\cos{(\omega + \theta)}$ and $\sin{(\omega + \theta)}$.
+
+Using the sine and cosine formulas presented at the beginning of this
+lecture, we have:
+
+$$
+\begin{aligned}
+\cos{(\omega + \theta)} = \frac{e^{i(\omega + \theta)} + e^{-i(\omega + \theta)}}{2} \\
+\sin{(\omega + \theta)} = \frac{e^{i(\omega + \theta)} - e^{-i(\omega + \theta)}}{2i}
+\end{aligned}
+$$
+
+We can also obtain the trigonometric identities as follows:
+
+$$
+\begin{aligned}
+\cos{(\omega + \theta)} + i \sin{(\omega + \theta)}
+&= e^{i(\omega + \theta)} \\
+&= e^{i\omega} e^{i\theta} \\
+&= (\cos{\omega} + i \sin{\omega})(\cos{\theta} + i \sin{\theta}) \\
+&= (\cos{\omega}\cos{\theta} - \sin{\omega}\sin{\theta}) +
+i (\cos{\omega}\sin{\theta} + \sin{\omega}\cos{\theta})
+\end{aligned}
+$$
+
+Since both real and imaginary parts of the above formula should be
+equal, we get:
+
+$$
+\begin{aligned}
+\cos{(\omega + \theta)} = \cos{\omega}\cos{\theta} - \sin{\omega}\sin{\theta} \\
+\sin{(\omega + \theta)} = \cos{\omega}\sin{\theta} + \sin{\omega}\cos{\theta}
+\end{aligned}
+$$
+
+The equations above are also known as the **angle sum identities**. We
+can verify the equations using the `simplify` function in the
+`sympy` package:
+
+```{code-cell} python3
+# Define symbols
+ω, θ = symbols('ω θ', real=True)
+
+# Verify
+print("cos(ω)cos(θ) - sin(ω)sin(θ) =",
+ simplify(cos(ω)*cos(θ) - sin(ω) * sin(θ)))
+print("cos(ω)sin(θ) + sin(ω)cos(θ) =",
+ simplify(cos(ω)*sin(θ) + sin(ω) * cos(θ)))
+```
+
+### Trigonometric Integrals
+
+We can also compute the trigonometric integrals using polar forms of
+complex numbers.
+
+For example, we want to solve the following integral:
+
+$$
+\int_{-\pi}^{\pi} \cos(\omega) \sin(\omega) \, d\omega
+$$
+
+Using Euler's formula, we have:
+
+$$
+\begin{aligned}
+\int \cos(\omega) \sin(\omega) \, d\omega
+&=
+\int
+\frac{(e^{i\omega} + e^{-i\omega})}{2}
+\frac{(e^{i\omega} - e^{-i\omega})}{2i}
+\, d\omega \\
+&=
+\frac{1}{4i}
+\int
+e^{2i\omega} - e^{-2i\omega}
+\, d\omega \\
+&=
+\frac{1}{4i}
+\bigg( \frac{-i}{2} e^{2i\omega} - \frac{i}{2} e^{-2i\omega} + C_1 \bigg) \\
+&=
+-\frac{1}{8}
+\bigg[ \bigg(e^{i\omega}\bigg)^2 + \bigg(e^{-i\omega}\bigg)^2 - 2 \bigg] + C_2 \\
+&=
+-\frac{1}{8} (e^{i\omega} - e^{-i\omega})^2 + C_2 \\
+&=
+\frac{1}{2} \bigg( \frac{e^{i\omega} - e^{-i\omega}}{2i} \bigg)^2 + C_2 \\
+&= \frac{1}{2} \sin^2(\omega) + C_2
+\end{aligned}
+$$
+
+and thus:
+
+$$
+\int_{-\pi}^{\pi} \cos(\omega) \sin(\omega) \, d\omega =
+\frac{1}{2}\sin^2(\pi) - \frac{1}{2}\sin^2(-\pi) = 0
+$$
+
+We can verify the analytical as well as numerical results using
+`integrate` in the `sympy` package:
+
+```{code-cell} python3
+# Set initial printing
+init_printing(use_latex="mathjax")
+
+ω = Symbol('ω')
+print('The analytical solution for integral of cos(ω)sin(ω) is:')
+integrate(cos(ω) * sin(ω), ω)
+```
+
+```{code-cell} python3
+print('The numerical solution for the integral of cos(ω)sin(ω) \
+from -π to π is:')
+integrate(cos(ω) * sin(ω), (ω, -π, π))
+```
+
+### Exercises
+
+```{exercise}
+:label: complex_ex1
+
+We invite the reader to verify analytically and with the `sympy` package the following two equalities:
+
+$$
+\int_{-\pi}^{\pi} \cos (\omega)^2 \, d\omega = \pi
+$$
+
+$$
+\int_{-\pi}^{\pi} \sin (\omega)^2 \, d\omega = \pi
+$$
+```
+
+```{solution-start} complex_ex1
+:class: dropdown
+```
+
+Let's import symbolic $\pi$ from `sympy`
+
+```{code-cell} ipython3
+# Import symbolic π from sympy
+from sympy import pi
+```
+
+```{code-cell} ipython3
+print('The analytical solution for the integral of cos(ω)**2 \
+from -π to π is:')
+
+integrate(cos(ω)**2, (ω, -pi, pi))
+```
+
+```{code-cell} ipython3
+print('The analytical solution for the integral of sin(ω)**2 \
+from -π to π is:')
+
+integrate(sin(ω)**2, (ω, -pi, pi))
+```
+
+```{solution-end}
+```
diff --git a/book/_build/html/_sources/cons_smooth.ipynb b/book/_build/html/_sources/cons_smooth.ipynb
new file mode 100644
index 0000000..e56b303
--- /dev/null
+++ b/book/_build/html/_sources/cons_smooth.ipynb
@@ -0,0 +1,1064 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "44edf43a",
+ "metadata": {},
+ "source": [
+ "# Consumption Smoothing\n",
+ "\n",
+ "## Overview\n",
+ "\n",
+ "\n",
+ "In this lecture, we'll study a famous model of the \"consumption function\" that Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`) proposed to fit some empirical data patterns that the original Keynesian consumption function described in this QuantEcon lecture {doc}`geometric series ` missed.\n",
+ "\n",
+ "In this lecture, we'll study what is often called the \"consumption-smoothing model\" using matrix multiplication and matrix inversion, the same tools that we used in this QuantEcon lecture {doc}`present values `. \n",
+ "\n",
+ "Formulas presented in {doc}`present value formulas` are at the core of the consumption-smoothing model because we shall use them to define a consumer's \"human wealth\".\n",
+ "\n",
+ "The key idea that inspired Milton Friedman was that a person's non-financial income, i.e., his or\n",
+ "her wages from working, could be viewed as a dividend stream from that person's ''human capital''\n",
+ "and that standard asset-pricing formulas could be applied to compute a person's\n",
+ "''non-financial wealth'' that capitalizes the earnings stream. \n",
+ "\n",
+ "```{note}\n",
+ "As we'll see in this QuantEcon lecture {doc}`equalizing difference model `,\n",
+ "Milton Friedman had used this idea in his PhD thesis at Columbia University, \n",
+ "eventually published as {cite}`kuznets1939incomes` and {cite}`friedman1954incomes`.\n",
+ "```\n",
+ "\n",
+ "It will take a while for a \"present value\" or asset price explicilty to appear in this lecture, but when it does it will be a key actor.\n",
+ "\n",
+ "\n",
+ "## Analysis\n",
+ "\n",
+ "As usual, we'll start by importing some Python modules."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "54a3d934",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "from collections import namedtuple"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "384c5c5d",
+ "metadata": {},
+ "source": [
+ "The model describes a consumer who lives from time $t=0, 1, \\ldots, T$, receives a stream $\\{y_t\\}_{t=0}^T$ of non-financial income and chooses a consumption stream $\\{c_t\\}_{t=0}^T$.\n",
+ "\n",
+ "We usually think of the non-financial income stream as coming from the person's salary from supplying labor. \n",
+ "\n",
+ "The model takes a non-financial income stream as an input, regarding it as \"exogenous\" in the sense of not being determined by the model. \n",
+ "\n",
+ "The consumer faces a gross interest rate of $R >1$ that is constant over time, at which she is free to borrow or lend, up to limits that we'll describe below.\n",
+ "\n",
+ "To set up the model, let \n",
+ "\n",
+ " * $T \\geq 2$ be a positive integer that constitutes a time-horizon. \n",
+ " * $y = \\{y_t\\}_{t=0}^T$ be an exogenous sequence of non-negative non-financial incomes $y_t$. \n",
+ " * $a = \\{a_t\\}_{t=0}^{T+1}$ be a sequence of financial wealth. \n",
+ " * $c = \\{c_t\\}_{t=0}^T$ be a sequence of non-negative consumption rates. \n",
+ " * $R \\geq 1$ be a fixed gross one period rate of return on financial assets. \n",
+ " * $\\beta \\in (0,1)$ be a fixed discount factor. \n",
+ " * $a_0$ be a given initial level of financial assets\n",
+ " * $a_{T+1} \\geq 0$ be a terminal condition on final assets. \n",
+ "\n",
+ "The sequence of financial wealth $a$ is to be determined by the model.\n",
+ "\n",
+ "We require it to satisfy two **boundary conditions**:\n",
+ "\n",
+ " * it must equal an exogenous value $a_0$ at time $0$ \n",
+ " * it must equal or exceed an exogenous value $a_{T+1}$ at time $T+1$.\n",
+ "\n",
+ "The **terminal condition** $a_{T+1} \\geq 0$ requires that the consumer not leave the model in debt.\n",
+ "\n",
+ "(We'll soon see that a utility maximizing consumer won't want to die leaving positive assets, so she'll arrange her affairs to make\n",
+ "$a_{T+1} = 0$.)\n",
+ "\n",
+ "The consumer faces a sequence of budget constraints that constrains sequences $(y, c, a)$\n",
+ "\n",
+ "$$\n",
+ "a_{t+1} = R (a_t+ y_t - c_t), \\quad t =0, 1, \\ldots T\n",
+ "$$ (eq:a_t)\n",
+ "\n",
+ "Equations {eq}`eq:a_t` constitute $T+1$ such budget constraints, one for each $t=0, 1, \\ldots, T$. \n",
+ "\n",
+ "Given a sequence $y$ of non-financial incomes, a large set of pairs $(a, c)$ of (financial wealth, consumption) sequences satisfy the sequence of budget constraints {eq}`eq:a_t`. \n",
+ "\n",
+ "Our model has the following logical flow.\n",
+ "\n",
+ " * start with an exogenous non-financial income sequence $y$, an initial financial wealth $a_0$, and \n",
+ " a candidate consumption path $c$.\n",
+ " \n",
+ " * use the system of equations {eq}`eq:a_t` for $t=0, \\ldots, T$ to compute a path $a$ of financial wealth\n",
+ " \n",
+ " * verify that $a_{T+1}$ satisfies the terminal wealth constraint $a_{T+1} \\geq 0$. \n",
+ " \n",
+ " * If it does, declare that the candidate path is **budget feasible**. \n",
+ " \n",
+ " * if the candidate consumption path is not budget feasible, propose a less greedy consumption path and start over\n",
+ " \n",
+ "Below, we'll describe how to execute these steps using linear algebra -- matrix inversion and multiplication.\n",
+ "\n",
+ "The above procedure seems like a sensible way to find \"budget-feasible\" consumption paths $c$, i.e., paths that are consistent\n",
+ "with the exogenous non-financial income stream $y$, the initial financial asset level $a_0$, and the terminal asset level $a_{T+1}$.\n",
+ "\n",
+ "In general, there are **many** budget feasible consumption paths $c$.\n",
+ "\n",
+ "Among all budget-feasible consumption paths, which one should a consumer want?\n",
+ "\n",
+ "\n",
+ "To answer this question, we shall eventually evaluate alternative budget feasible consumption paths $c$ using the following utility functional or **welfare criterion**:\n",
+ "\n",
+ "```{math}\n",
+ ":label: welfare\n",
+ "\n",
+ "W = \\sum_{t=0}^T \\beta^t (g_1 c_t - \\frac{g_2}{2} c_t^2 )\n",
+ "```\n",
+ "\n",
+ "where $g_1 > 0, g_2 > 0$. \n",
+ "\n",
+ "When $\\beta R \\approx 1$, the fact that the utility function $g_1 c_t - \\frac{g_2}{2} c_t^2$ has diminishing marginal utility imparts a preference for consumption that is very smooth. \n",
+ "\n",
+ "Indeed, we shall see that when $\\beta R = 1$ (a condition assumed by Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`), criterion {eq}`welfare` assigns higher welfare to smoother consumption paths.\n",
+ "\n",
+ "By **smoother** we mean as close as possible to being constant over time. \n",
+ "\n",
+ "The preference for smooth consumption paths that is built into the model gives it the name \"consumption-smoothing model\".\n",
+ "\n",
+ "Let's dive in and do some calculations that will help us understand how the model works. \n",
+ "\n",
+ "Here we use default parameters $R = 1.05$, $g_1 = 1$, $g_2 = 1/2$, and $T = 65$. \n",
+ "\n",
+ "We create a Python **namedtuple** to store these parameters with default values."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3ca5970e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ConsumptionSmoothing = namedtuple(\"ConsumptionSmoothing\", \n",
+ " [\"R\", \"g1\", \"g2\", \"β_seq\", \"T\"])\n",
+ "\n",
+ "def create_consumption_smoothing_model(R=1.05, g1=1, g2=1/2, T=65):\n",
+ " β = 1/R\n",
+ " β_seq = np.array([β**i for i in range(T+1)])\n",
+ " return ConsumptionSmoothing(R, g1, g2, \n",
+ " β_seq, T)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "dff3eadf",
+ "metadata": {},
+ "source": [
+ "## Friedman-Hall consumption-smoothing model\n",
+ "\n",
+ "A key object is what Milton Friedman called \"human\" or \"non-financial\" wealth at time $0$:\n",
+ "\n",
+ "\n",
+ "$$\n",
+ "h_0 \\equiv \\sum_{t=0}^T R^{-t} y_t = \\begin{bmatrix} 1 & R^{-1} & \\cdots & R^{-T} \\end{bmatrix}\n",
+ "\\begin{bmatrix} y_0 \\cr y_1 \\cr \\vdots \\cr y_T \\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "Human or non-financial wealth at time $0$ is evidently just the present value of the consumer's non-financial income stream $y$. \n",
+ "\n",
+ "Formally it very much resembles the asset price that we computed in this QuantEcon lecture {doc}`present values `.\n",
+ "\n",
+ "Indeed, this is why Milton Friedman called it \"human capital\". \n",
+ "\n",
+ "By iterating on equation {eq}`eq:a_t` and imposing the terminal condition \n",
+ "\n",
+ "$$\n",
+ "a_{T+1} = 0,\n",
+ "$$\n",
+ "\n",
+ "it is possible to convert a sequence of budget constraints {eq}`eq:a_t` into a single intertemporal constraint\n",
+ "\n",
+ "$$ \n",
+ "\\sum_{t=0}^T R^{-t} c_t = a_0 + h_0. \n",
+ "$$ (eq:budget_intertemp)\n",
+ "\n",
+ "Equation {eq}`eq:budget_intertemp` says that the present value of the consumption stream equals the sum of financial and non-financial (or human) wealth.\n",
+ "\n",
+ "Robert Hall {cite}`Hall1978` showed that when $\\beta R = 1$, a condition Milton Friedman had also assumed, it is \"optimal\" for a consumer to smooth consumption by setting \n",
+ "\n",
+ "$$ \n",
+ "c_t = c_0 \\quad t =0, 1, \\ldots, T\n",
+ "$$\n",
+ "\n",
+ "(Later we'll present a \"variational argument\" that shows that this constant path maximizes\n",
+ "criterion {eq}`welfare` when $\\beta R =1$.)\n",
+ "\n",
+ "In this case, we can use the intertemporal budget constraint to write \n",
+ "\n",
+ "$$\n",
+ "c_t = c_0 = \\left(\\sum_{t=0}^T R^{-t}\\right)^{-1} (a_0 + h_0), \\quad t= 0, 1, \\ldots, T.\n",
+ "$$ (eq:conssmoothing)\n",
+ "\n",
+ "Equation {eq}`eq:conssmoothing` is the consumption-smoothing model in a nutshell.\n",
+ "\n",
+ "\n",
+ "## Mechanics of consumption-smoothing model \n",
+ "\n",
+ "As promised, we'll provide step-by-step instructions on how to use linear algebra, readily implemented in Python, to compute all objects in play in the consumption-smoothing model.\n",
+ "\n",
+ "In the calculations below, we'll set default values of $R > 1$, e.g., $R = 1.05$, and $\\beta = R^{-1}$.\n",
+ "\n",
+ "### Step 1\n",
+ "\n",
+ "For a $(T+1) \\times 1$ vector $y$, use matrix algebra to compute $h_0$\n",
+ "\n",
+ "$$\n",
+ "h_0 = \\sum_{t=0}^T R^{-t} y_t = \\begin{bmatrix} 1 & R^{-1} & \\cdots & R^{-T} \\end{bmatrix}\n",
+ "\\begin{bmatrix} y_0 \\cr y_1 \\cr \\vdots \\cr y_T \\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "### Step 2\n",
+ "\n",
+ "Compute an time $0$ consumption $c_0 $ :\n",
+ "\n",
+ "$$\n",
+ "c_t = c_0 = \\left( \\frac{1 - R^{-1}}{1 - R^{-(T+1)}} \\right) (a_0 + \\sum_{t=0}^T R^{-t} y_t ) , \\quad t = 0, 1, \\ldots, T\n",
+ "$$\n",
+ "\n",
+ "### Step 3\n",
+ "\n",
+ "Use the system of equations {eq}`eq:a_t` for $t=0, \\ldots, T$ to compute a path $a$ of financial wealth.\n",
+ "\n",
+ "To do this, we translate that system of difference equations into a single matrix equation as follows:\n",
+ "\n",
+ "\n",
+ "$$\n",
+ "\\begin{bmatrix} \n",
+ "1 & 0 & 0 & \\cdots & 0 & 0 & 0 \\cr\n",
+ "-R & 1 & 0 & \\cdots & 0 & 0 & 0 \\cr\n",
+ "0 & -R & 1 & \\cdots & 0 & 0 & 0 \\cr\n",
+ "\\vdots &\\vdots & \\vdots & \\cdots & \\vdots & \\vdots & \\vdots \\cr\n",
+ "0 & 0 & 0 & \\cdots & -R & 1 & 0 \\cr\n",
+ "0 & 0 & 0 & \\cdots & 0 & -R & 1\n",
+ "\\end{bmatrix} \n",
+ "\\begin{bmatrix} a_1 \\cr a_2 \\cr a_3 \\cr \\vdots \\cr a_T \\cr a_{T+1} \n",
+ "\\end{bmatrix}\n",
+ "= R \n",
+ "\\begin{bmatrix} y_0 + a_0 - c_0 \\cr y_1 - c_0 \\cr y_2 - c_0 \\cr \\vdots\\cr y_{T-1} - c_0 \\cr y_T - c_0\n",
+ "\\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "Multiply both sides by the inverse of the matrix on the left side to compute\n",
+ "\n",
+ "$$\n",
+ " \\begin{bmatrix} a_1 \\cr a_2 \\cr a_3 \\cr \\vdots \\cr a_T \\cr a_{T+1} \\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "\n",
+ "Because we have built into our calculations that the consumer leaves the model with exactly zero assets, just barely satisfying the\n",
+ "terminal condition that $a_{T+1} \\geq 0$, it should turn out that \n",
+ "\n",
+ "$$\n",
+ "a_{T+1} = 0.\n",
+ "$$\n",
+ " \n",
+ "\n",
+ "Let's verify this with Python code.\n",
+ "\n",
+ "First we implement the model with `compute_optimal`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "450ac0b9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def compute_optimal(model, a0, y_seq):\n",
+ " R, T = model.R, model.T\n",
+ "\n",
+ " # non-financial wealth\n",
+ " h0 = model.β_seq @ y_seq # since β = 1/R\n",
+ "\n",
+ " # c0\n",
+ " c0 = (1 - 1/R) / (1 - (1/R)**(T+1)) * (a0 + h0)\n",
+ " c_seq = c0*np.ones(T+1)\n",
+ "\n",
+ " # verify\n",
+ " A = np.diag(-R*np.ones(T), k=-1) + np.eye(T+1)\n",
+ " b = y_seq - c_seq\n",
+ " b[0] = b[0] + a0\n",
+ "\n",
+ " a_seq = np.linalg.inv(A) @ b\n",
+ " a_seq = np.concatenate([[a0], a_seq])\n",
+ "\n",
+ " return c_seq, a_seq, h0"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1bf3db2e",
+ "metadata": {},
+ "source": [
+ "We use an example where the consumer inherits $a_0<0$.\n",
+ "\n",
+ "This can be interpreted as a student debt.\n",
+ "\n",
+ "The non-financial process $\\{y_t\\}_{t=0}^{T}$ is constant and positive up to $t=45$ and then becomes zero afterward.\n",
+ "\n",
+ "The drop in non-financial income late in life reflects retirement from work."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "446fc6a3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Financial wealth\n",
+ "a0 = -2 # such as \"student debt\"\n",
+ "\n",
+ "# non-financial Income process\n",
+ "y_seq = np.concatenate([np.ones(46), np.zeros(20)])\n",
+ "\n",
+ "cs_model = create_consumption_smoothing_model()\n",
+ "c_seq, a_seq, h0 = compute_optimal(cs_model, a0, y_seq)\n",
+ "\n",
+ "print('check a_T+1=0:', \n",
+ " np.abs(a_seq[-1] - 0) <= 1e-8)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "dc48ad3d",
+ "metadata": {},
+ "source": [
+ "The graphs below show paths of non-financial income, consumption, and financial assets."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9a91219f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Sequence Length\n",
+ "T = cs_model.T\n",
+ "\n",
+ "plt.plot(range(T+1), y_seq, label='non-financial income')\n",
+ "plt.plot(range(T+1), c_seq, label='consumption')\n",
+ "plt.plot(range(T+2), a_seq, label='financial wealth')\n",
+ "plt.plot(range(T+2), np.zeros(T+2), '--')\n",
+ "\n",
+ "plt.legend()\n",
+ "plt.xlabel(r'$t$')\n",
+ "plt.ylabel(r'$c_t,y_t,a_t$')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "81a5b72e",
+ "metadata": {},
+ "source": [
+ "Note that $a_{T+1} = 0$, as anticipated.\n",
+ "\n",
+ "We can evaluate welfare criterion {eq}`welfare`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e3bb4b4c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def welfare(model, c_seq):\n",
+ " β_seq, g1, g2 = model.β_seq, model.g1, model.g2\n",
+ "\n",
+ " u_seq = g1 * c_seq - g2/2 * c_seq**2\n",
+ " return β_seq @ u_seq\n",
+ "\n",
+ "print('Welfare:', welfare(cs_model, c_seq))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "14a6a07e",
+ "metadata": {},
+ "source": [
+ "### Experiments\n",
+ "\n",
+ "In this section we describe how a consumption sequence would optimally respond to different sequences sequences of non-financial income.\n",
+ "\n",
+ "First we create a function `plot_cs` that generates graphs for different instances of the consumption-smoothing model `cs_model`.\n",
+ "\n",
+ "This will help us avoid rewriting code to plot outcomes for different non-financial income sequences."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ad68f886",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plot_cs(model, # consumption-smoothing model \n",
+ " a0, # initial financial wealth\n",
+ " y_seq # non-financial income process\n",
+ " ):\n",
+ " \n",
+ " # Compute optimal consumption\n",
+ " c_seq, a_seq, h0 = compute_optimal(model, a0, y_seq)\n",
+ " \n",
+ " # Sequence length\n",
+ " T = cs_model.T\n",
+ " \n",
+ " # Generate plot\n",
+ " plt.plot(range(T+1), y_seq, label='non-financial income')\n",
+ " plt.plot(range(T+1), c_seq, label='consumption')\n",
+ " plt.plot(range(T+2), a_seq, label='financial wealth')\n",
+ " plt.plot(range(T+2), np.zeros(T+2), '--')\n",
+ " \n",
+ " plt.legend()\n",
+ " plt.xlabel(r'$t$')\n",
+ " plt.ylabel(r'$c_t,y_t,a_t$')\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "37df1d34",
+ "metadata": {},
+ "source": [
+ "In the experiments below, please study how consumption and financial asset sequences vary across different sequences for non-financial income.\n",
+ "\n",
+ "#### Experiment 1: one-time gain/loss\n",
+ "\n",
+ "We first assume a one-time windfall of $W_0$ in year 21 of the income sequence $y$. \n",
+ "\n",
+ "We'll make $W_0$ big - positive to indicate a one-time windfall, and negative to indicate a one-time \"disaster\"."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d0a87fa7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Windfall W_0 = 2.5\n",
+ "y_seq_pos = np.concatenate([np.ones(21), np.array([2.5]), np.ones(24), np.zeros(20)])\n",
+ "\n",
+ "plot_cs(cs_model, a0, y_seq_pos)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ded293e0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Disaster W_0 = -2.5\n",
+ "y_seq_neg = np.concatenate([np.ones(21), np.array([-2.5]), np.ones(24), np.zeros(20)])\n",
+ "\n",
+ "plot_cs(cs_model, a0, y_seq_neg)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "872538c7",
+ "metadata": {},
+ "source": [
+ "#### Experiment 2: permanent wage gain/loss\n",
+ "\n",
+ "Now we assume a permanent increase in income of $W$ in year 21 of the $y$-sequence.\n",
+ "\n",
+ "Again we can study positive and negative cases"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "95901c46",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Positive permanent income change W = 0.5 when t >= 21\n",
+ "y_seq_pos = np.concatenate(\n",
+ " [np.ones(21), 1.5*np.ones(25), np.zeros(20)])\n",
+ "\n",
+ "plot_cs(cs_model, a0, y_seq_pos)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4b0081a4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Negative permanent income change W = -0.5 when t >= 21\n",
+ "y_seq_neg = np.concatenate(\n",
+ " [np.ones(21), .5*np.ones(25), np.zeros(20)])\n",
+ "\n",
+ "plot_cs(cs_model, a0, y_seq_neg)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "fa00569d",
+ "metadata": {},
+ "source": [
+ "#### Experiment 3: a late starter\n",
+ "\n",
+ "Now we simulate a $y$ sequence in which a person gets zero for 46 years, and then works and gets 1 for the last 20 years of life (a \"late starter\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "963f1feb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Late starter\n",
+ "y_seq_late = np.concatenate(\n",
+ " [np.zeros(46), np.ones(20)])\n",
+ "\n",
+ "plot_cs(cs_model, a0, y_seq_late)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6846935b",
+ "metadata": {},
+ "source": [
+ "#### Experiment 4: geometric earner\n",
+ "\n",
+ "Now we simulate a geometric $y$ sequence in which a person gets $y_t = \\lambda^t y_0$ in first 46 years.\n",
+ "\n",
+ "We first experiment with $\\lambda = 1.05$"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1de99b8f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Geometric earner parameters where λ = 1.05\n",
+ "λ = 1.05\n",
+ "y_0 = 1\n",
+ "t_max = 46\n",
+ "\n",
+ "# Generate geometric y sequence\n",
+ "geo_seq = λ ** np.arange(t_max) * y_0 \n",
+ "y_seq_geo = np.concatenate(\n",
+ " [geo_seq, np.zeros(20)])\n",
+ "\n",
+ "plot_cs(cs_model, a0, y_seq_geo)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b8e6b1d8",
+ "metadata": {},
+ "source": [
+ "Now we show the behavior when $\\lambda = 0.95$"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "939e957d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "λ = 0.95\n",
+ "\n",
+ "geo_seq = λ ** np.arange(t_max) * y_0 \n",
+ "y_seq_geo = np.concatenate(\n",
+ " [geo_seq, np.zeros(20)])\n",
+ "\n",
+ "plot_cs(cs_model, a0, y_seq_geo)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b613028a",
+ "metadata": {},
+ "source": [
+ "What happens when $\\lambda$ is negative"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "fa5c335d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "λ = -0.95\n",
+ "\n",
+ "geo_seq = λ ** np.arange(t_max) * y_0 \n",
+ "y_seq_geo = np.concatenate(\n",
+ " [geo_seq, np.zeros(20)])\n",
+ "\n",
+ "plot_cs(cs_model, a0, y_seq_geo)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "84ff0098",
+ "metadata": {},
+ "source": [
+ "### Feasible consumption variations\n",
+ "\n",
+ "We promised to justify our claim that a constant consumption play $c_t = c_0$ for all\n",
+ "$t$ is optimal. \n",
+ "\n",
+ "Let's do that now.\n",
+ "\n",
+ "The approach we'll take is an elementary example of the \"calculus of variations\". \n",
+ "\n",
+ "Let's dive in and see what the key idea is. \n",
+ "\n",
+ "To explore what types of consumption paths are welfare-improving, we shall create an **admissible consumption path variation sequence** $\\{v_t\\}_{t=0}^T$\n",
+ "that satisfies\n",
+ "\n",
+ "$$\n",
+ "\\sum_{t=0}^T R^{-t} v_t = 0\n",
+ "$$\n",
+ "\n",
+ "This equation says that the **present value** of admissible consumption path variations must be zero.\n",
+ "\n",
+ "So once again, we encounter a formula for the present value of an \"asset\":\n",
+ "\n",
+ " * we require that the present value of consumption path variations be zero.\n",
+ "\n",
+ "Here we'll restrict ourselves to a two-parameter class of admissible consumption path variations\n",
+ "of the form\n",
+ "\n",
+ "$$\n",
+ "v_t = \\xi_1 \\phi^t - \\xi_0\n",
+ "$$\n",
+ "\n",
+ "We say two and not three-parameter class because $\\xi_0$ will be a function of $(\\phi, \\xi_1; R)$ that guarantees that the variation sequence is feasible. \n",
+ "\n",
+ "Let's compute that function.\n",
+ "\n",
+ "We require\n",
+ "\n",
+ "$$\n",
+ "\\sum_{t=0}^T R^{-t}\\left[ \\xi_1 \\phi^t - \\xi_0 \\right] = 0\n",
+ "$$\n",
+ "\n",
+ "which implies that\n",
+ "\n",
+ "$$\n",
+ "\\xi_1 \\sum_{t=0}^T \\phi_t R^{-t} - \\xi_0 \\sum_{t=0}^T R^{-t} = 0\n",
+ "$$\n",
+ "\n",
+ "which implies that\n",
+ "\n",
+ "$$\n",
+ "\\xi_1 \\frac{1 - (\\phi R^{-1})^{T+1}}{1 - \\phi R^{-1}} - \\xi_0 \\frac{1 - R^{-(T+1)}}{1-R^{-1} } =0\n",
+ "$$\n",
+ "\n",
+ "which implies that\n",
+ "\n",
+ "$$\n",
+ "\\xi_0 = \\xi_0(\\phi, \\xi_1; R) = \\xi_1 \\left(\\frac{1 - R^{-1}}{1 - R^{-(T+1)}}\\right) \\left(\\frac{1 - (\\phi R^{-1})^{T+1}}{1 - \\phi R^{-1}}\\right)\n",
+ "$$ \n",
+ "\n",
+ "This is our formula for $\\xi_0$. \n",
+ "\n",
+ "**Key Idea:** if $c^o$ is a budget-feasible consumption path, then so is $c^o + v$,\n",
+ "where $v$ is a budget-feasible variation.\n",
+ "\n",
+ "Given $R$, we thus have a two parameter class of budget feasible variations $v$ that we can use\n",
+ "to compute alternative consumption paths, then evaluate their welfare.\n",
+ "\n",
+ "Now let's compute and plot consumption path variations"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c40c7a92",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def compute_variation(model, ξ1, ϕ, a0, y_seq, verbose=1):\n",
+ " R, T, β_seq = model.R, model.T, model.β_seq\n",
+ "\n",
+ " ξ0 = ξ1*((1 - 1/R) / (1 - (1/R)**(T+1))) * ((1 - (ϕ/R)**(T+1)) / (1 - ϕ/R))\n",
+ " v_seq = np.array([(ξ1*ϕ**t - ξ0) for t in range(T+1)])\n",
+ " \n",
+ " if verbose == 1:\n",
+ " print('check feasible:', np.isclose(β_seq @ v_seq, 0)) # since β = 1/R\n",
+ "\n",
+ " c_opt, _, _ = compute_optimal(model, a0, y_seq)\n",
+ " cvar_seq = c_opt + v_seq\n",
+ "\n",
+ " return cvar_seq"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4b10e183",
+ "metadata": {},
+ "source": [
+ "We visualize variations for $\\xi_1 \\in \\{.01, .05\\}$ and $\\phi \\in \\{.95, 1.02\\}$"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "730ce577",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "\n",
+ "ξ1s = [.01, .05]\n",
+ "ϕs= [.95, 1.02]\n",
+ "colors = {.01: 'tab:blue', .05: 'tab:green'}\n",
+ "\n",
+ "params = np.array(np.meshgrid(ξ1s, ϕs)).T.reshape(-1, 2)\n",
+ "\n",
+ "for i, param in enumerate(params):\n",
+ " ξ1, ϕ = param\n",
+ " print(f'variation {i}: ξ1={ξ1}, ϕ={ϕ}')\n",
+ " cvar_seq = compute_variation(model=cs_model, \n",
+ " ξ1=ξ1, ϕ=ϕ, a0=a0, \n",
+ " y_seq=y_seq)\n",
+ " print(f'welfare={welfare(cs_model, cvar_seq)}')\n",
+ " print('-'*64)\n",
+ " if i % 2 == 0:\n",
+ " ls = '-.'\n",
+ " else: \n",
+ " ls = '-' \n",
+ " ax.plot(range(T+1), cvar_seq, ls=ls, \n",
+ " color=colors[ξ1], \n",
+ " label=fr'$\\xi_1 = {ξ1}, \\phi = {ϕ}$')\n",
+ "\n",
+ "plt.plot(range(T+1), c_seq, \n",
+ " color='orange', label=r'Optimal $\\vec{c}$ ')\n",
+ "\n",
+ "plt.legend()\n",
+ "plt.xlabel(r'$t$')\n",
+ "plt.ylabel(r'$c_t$')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a17172c0",
+ "metadata": {},
+ "source": [
+ "We can even use the Python `np.gradient` command to compute derivatives of welfare with respect to our two parameters. \n",
+ "\n",
+ "We are teaching the key idea beneath the **calculus of variations**.\n",
+ "\n",
+ "First, we define the welfare with respect to $\\xi_1$ and $\\phi$"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d0b98755",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def welfare_rel(ξ1, ϕ):\n",
+ " \"\"\"\n",
+ " Compute welfare of variation sequence \n",
+ " for given ϕ, ξ1 with a consumption-smoothing model\n",
+ " \"\"\"\n",
+ " \n",
+ " cvar_seq = compute_variation(cs_model, ξ1=ξ1, \n",
+ " ϕ=ϕ, a0=a0, \n",
+ " y_seq=y_seq, \n",
+ " verbose=0)\n",
+ " return welfare(cs_model, cvar_seq)\n",
+ "\n",
+ "# Vectorize the function to allow array input\n",
+ "welfare_vec = np.vectorize(welfare_rel)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "54e92816",
+ "metadata": {},
+ "source": [
+ "Then we can visualize the relationship between welfare and $\\xi_1$ and compute its derivatives"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d83ab1eb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ξ1_arr = np.linspace(-0.5, 0.5, 20)\n",
+ "\n",
+ "plt.plot(ξ1_arr, welfare_vec(ξ1_arr, 1.02))\n",
+ "plt.ylabel('welfare')\n",
+ "plt.xlabel(r'$\\xi_1$')\n",
+ "plt.show()\n",
+ "\n",
+ "welfare_grad = welfare_vec(ξ1_arr, 1.02)\n",
+ "welfare_grad = np.gradient(welfare_grad)\n",
+ "plt.plot(ξ1_arr, welfare_grad)\n",
+ "plt.ylabel('derivative of welfare')\n",
+ "plt.xlabel(r'$\\xi_1$')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "48eee396",
+ "metadata": {},
+ "source": [
+ "The same can be done on $\\phi$"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5acbc447",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ϕ_arr = np.linspace(-0.5, 0.5, 20)\n",
+ "\n",
+ "plt.plot(ξ1_arr, welfare_vec(0.05, ϕ_arr))\n",
+ "plt.ylabel('welfare')\n",
+ "plt.xlabel(r'$\\phi$')\n",
+ "plt.show()\n",
+ "\n",
+ "welfare_grad = welfare_vec(0.05, ϕ_arr)\n",
+ "welfare_grad = np.gradient(welfare_grad)\n",
+ "plt.plot(ξ1_arr, welfare_grad)\n",
+ "plt.ylabel('derivative of welfare')\n",
+ "plt.xlabel(r'$\\phi$')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "06411588",
+ "metadata": {},
+ "source": [
+ "## Wrapping up the consumption-smoothing model\n",
+ "\n",
+ "The consumption-smoothing model of Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`) is a cornerstone of modern macro that has important ramifications for the size of the Keynesian \"fiscal policy multiplier\" described briefly in\n",
+ "QuantEcon lecture {doc}`geometric series `. \n",
+ "\n",
+ "In particular, it **lowers** the government expenditure multiplier relative to one implied by\n",
+ "the original Keynesian consumption function presented in {doc}`geometric series `.\n",
+ "\n",
+ "Friedman's work opened the door to an enlightening literature on the aggregate consumption function and associated government expenditure multipliers that\n",
+ "remains active today. \n",
+ "\n",
+ "\n",
+ "## Appendix: solving difference equations with linear algebra\n",
+ "\n",
+ "In the preceding sections we have used linear algebra to solve a consumption-smoothing model. \n",
+ "\n",
+ "The same tools from linear algebra -- matrix multiplication and matrix inversion -- can be used to study many other dynamic models.\n",
+ "\n",
+ "We'll conclude this lecture by giving a couple of examples.\n",
+ "\n",
+ "We'll describe a useful way of representing and \"solving\" linear difference equations. \n",
+ "\n",
+ "To generate some $y$ vectors, we'll just write down a linear difference equation\n",
+ "with appropriate initial conditions and then use linear algebra to solve it.\n",
+ "\n",
+ "### First-order difference equation\n",
+ "\n",
+ "We'll start with a first-order linear difference equation for $\\{y_t\\}_{t=0}^T$:\n",
+ "\n",
+ "$$\n",
+ "y_{t} = \\lambda y_{t-1}, \\quad t = 1, 2, \\ldots, T\n",
+ "$$\n",
+ "\n",
+ "where $y_0$ is a given initial condition.\n",
+ "\n",
+ "\n",
+ "We can cast this set of $T$ equations as a single matrix equation\n",
+ "\n",
+ "$$\n",
+ "\\begin{bmatrix} \n",
+ "1 & 0 & 0 & \\cdots & 0 & 0 \\cr\n",
+ "-\\lambda & 1 & 0 & \\cdots & 0 & 0 \\cr\n",
+ "0 & -\\lambda & 1 & \\cdots & 0 & 0 \\cr\n",
+ " \\vdots & \\vdots & \\vdots & \\cdots & \\vdots & \\vdots \\cr\n",
+ "0 & 0 & 0 & \\cdots & -\\lambda & 1 \n",
+ "\\end{bmatrix} \n",
+ "\\begin{bmatrix}\n",
+ "y_1 \\cr y_2 \\cr y_3 \\cr \\vdots \\cr y_T \n",
+ "\\end{bmatrix}\n",
+ "= \n",
+ "\\begin{bmatrix} \n",
+ "\\lambda y_0 \\cr 0 \\cr 0 \\cr \\vdots \\cr 0 \n",
+ "\\end{bmatrix}\n",
+ "$$ (eq:first_order_lin_diff)\n",
+ "\n",
+ "\n",
+ "Multiplying both sides of {eq}`eq:first_order_lin_diff` by the inverse of the matrix on the left provides the solution\n",
+ "\n",
+ "```{math}\n",
+ ":label: fst_ord_inverse\n",
+ "\n",
+ "\\begin{bmatrix} \n",
+ "y_1 \\cr y_2 \\cr y_3 \\cr \\vdots \\cr y_T \n",
+ "\\end{bmatrix} \n",
+ "= \n",
+ "\\begin{bmatrix} \n",
+ "1 & 0 & 0 & \\cdots & 0 & 0 \\cr\n",
+ "\\lambda & 1 & 0 & \\cdots & 0 & 0 \\cr\n",
+ "\\lambda^2 & \\lambda & 1 & \\cdots & 0 & 0 \\cr\n",
+ " \\vdots & \\vdots & \\vdots & \\cdots & \\vdots & \\vdots \\cr\n",
+ "\\lambda^{T-1} & \\lambda^{T-2} & \\lambda^{T-3} & \\cdots & \\lambda & 1 \n",
+ "\\end{bmatrix}\n",
+ "\\begin{bmatrix} \n",
+ "\\lambda y_0 \\cr 0 \\cr 0 \\cr \\vdots \\cr 0 \n",
+ "\\end{bmatrix}\n",
+ "```\n",
+ "\n",
+ "```{exercise}\n",
+ ":label: consmooth_ex1\n",
+ "\n",
+ "To get {eq}`fst_ord_inverse`, we multiplied both sides of {eq}`eq:first_order_lin_diff` by the inverse of the matrix $A$. Please confirm that \n",
+ "\n",
+ "$$\n",
+ "\\begin{bmatrix} \n",
+ "1 & 0 & 0 & \\cdots & 0 & 0 \\cr\n",
+ "\\lambda & 1 & 0 & \\cdots & 0 & 0 \\cr\n",
+ "\\lambda^2 & \\lambda & 1 & \\cdots & 0 & 0 \\cr\n",
+ " \\vdots & \\vdots & \\vdots & \\cdots & \\vdots & \\vdots \\cr\n",
+ "\\lambda^{T-1} & \\lambda^{T-2} & \\lambda^{T-3} & \\cdots & \\lambda & 1 \n",
+ "\\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "is the inverse of $A$ and check that $A A^{-1} = I$\n",
+ "\n",
+ "```\n",
+ "\n",
+ "### Second-order difference equation\n",
+ "\n",
+ "A second-order linear difference equation for $\\{y_t\\}_{t=0}^T$ is\n",
+ "\n",
+ "$$\n",
+ "y_{t} = \\lambda_1 y_{t-1} + \\lambda_2 y_{t-2}, \\quad t = 1, 2, \\ldots, T\n",
+ "$$\n",
+ "\n",
+ "where now $y_0$ and $y_{-1}$ are two given initial equations determined outside the model. \n",
+ "\n",
+ "As we did with the first-order difference equation, we can cast this set of $T$ equations as a single matrix equation\n",
+ "\n",
+ "$$\n",
+ "\\begin{bmatrix} \n",
+ "1 & 0 & 0 & \\cdots & 0 & 0 & 0 \\cr\n",
+ "-\\lambda_1 & 1 & 0 & \\cdots & 0 & 0 & 0 \\cr\n",
+ "-\\lambda_2 & -\\lambda_1 & 1 & \\cdots & 0 & 0 & 0 \\cr\n",
+ " \\vdots & \\vdots & \\vdots & \\cdots & \\vdots & \\vdots \\cr\n",
+ "0 & 0 & 0 & \\cdots & -\\lambda_2 & -\\lambda_1 & 1 \n",
+ "\\end{bmatrix} \n",
+ "\\begin{bmatrix} \n",
+ "y_1 \\cr y_2 \\cr y_3 \\cr \\vdots \\cr y_T \n",
+ "\\end{bmatrix}\n",
+ "= \n",
+ "\\begin{bmatrix} \n",
+ "\\lambda_1 y_0 + \\lambda_2 y_{-1} \\cr \\lambda_2 y_0 \\cr 0 \\cr \\vdots \\cr 0 \n",
+ "\\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "Multiplying both sides by inverse of the matrix on the left again provides the solution.\n",
+ "\n",
+ "```{exercise}\n",
+ ":label: consmooth_ex2\n",
+ "\n",
+ "As an exercise, we ask you to represent and solve a **third-order linear difference equation**.\n",
+ "How many initial conditions must you specify?\n",
+ "```"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.16.1"
+ }
+ },
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "source_map": [
+ 12,
+ 44,
+ 48,
+ 139,
+ 148,
+ 264,
+ 284,
+ 294,
+ 306,
+ 310,
+ 323,
+ 329,
+ 337,
+ 347,
+ 369,
+ 379,
+ 386,
+ 391,
+ 399,
+ 407,
+ 413,
+ 419,
+ 425,
+ 433,
+ 445,
+ 449,
+ 457,
+ 461,
+ 469,
+ 541,
+ 555,
+ 560,
+ 592,
+ 601,
+ 616,
+ 621,
+ 635,
+ 640,
+ 654
+ ]
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/cons_smooth.md b/book/_build/html/_sources/cons_smooth.md
new file mode 100644
index 0000000..2719baa
--- /dev/null
+++ b/book/_build/html/_sources/cons_smooth.md
@@ -0,0 +1,788 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.16.1
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+
+# Consumption Smoothing
+
+## Overview
+
+
+In this lecture, we'll study a famous model of the "consumption function" that Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`) proposed to fit some empirical data patterns that the original Keynesian consumption function described in this QuantEcon lecture {doc}`geometric series ` missed.
+
+In this lecture, we'll study what is often called the "consumption-smoothing model" using matrix multiplication and matrix inversion, the same tools that we used in this QuantEcon lecture {doc}`present values `.
+
+Formulas presented in {doc}`present value formulas` are at the core of the consumption-smoothing model because we shall use them to define a consumer's "human wealth".
+
+The key idea that inspired Milton Friedman was that a person's non-financial income, i.e., his or
+her wages from working, could be viewed as a dividend stream from that person's ''human capital''
+and that standard asset-pricing formulas could be applied to compute a person's
+''non-financial wealth'' that capitalizes the earnings stream.
+
+```{note}
+As we'll see in this QuantEcon lecture {doc}`equalizing difference model `,
+Milton Friedman had used this idea in his PhD thesis at Columbia University,
+eventually published as {cite}`kuznets1939incomes` and {cite}`friedman1954incomes`.
+```
+
+It will take a while for a "present value" or asset price explicilty to appear in this lecture, but when it does it will be a key actor.
+
+
+## Analysis
+
+As usual, we'll start by importing some Python modules.
+
+```{code-cell} ipython3
+import numpy as np
+import matplotlib.pyplot as plt
+from collections import namedtuple
+```
+
+
+The model describes a consumer who lives from time $t=0, 1, \ldots, T$, receives a stream $\{y_t\}_{t=0}^T$ of non-financial income and chooses a consumption stream $\{c_t\}_{t=0}^T$.
+
+We usually think of the non-financial income stream as coming from the person's salary from supplying labor.
+
+The model takes a non-financial income stream as an input, regarding it as "exogenous" in the sense of not being determined by the model.
+
+The consumer faces a gross interest rate of $R >1$ that is constant over time, at which she is free to borrow or lend, up to limits that we'll describe below.
+
+To set up the model, let
+
+ * $T \geq 2$ be a positive integer that constitutes a time-horizon.
+ * $y = \{y_t\}_{t=0}^T$ be an exogenous sequence of non-negative non-financial incomes $y_t$.
+ * $a = \{a_t\}_{t=0}^{T+1}$ be a sequence of financial wealth.
+ * $c = \{c_t\}_{t=0}^T$ be a sequence of non-negative consumption rates.
+ * $R \geq 1$ be a fixed gross one period rate of return on financial assets.
+ * $\beta \in (0,1)$ be a fixed discount factor.
+ * $a_0$ be a given initial level of financial assets
+ * $a_{T+1} \geq 0$ be a terminal condition on final assets.
+
+The sequence of financial wealth $a$ is to be determined by the model.
+
+We require it to satisfy two **boundary conditions**:
+
+ * it must equal an exogenous value $a_0$ at time $0$
+ * it must equal or exceed an exogenous value $a_{T+1}$ at time $T+1$.
+
+The **terminal condition** $a_{T+1} \geq 0$ requires that the consumer not leave the model in debt.
+
+(We'll soon see that a utility maximizing consumer won't want to die leaving positive assets, so she'll arrange her affairs to make
+$a_{T+1} = 0$.)
+
+The consumer faces a sequence of budget constraints that constrains sequences $(y, c, a)$
+
+$$
+a_{t+1} = R (a_t+ y_t - c_t), \quad t =0, 1, \ldots T
+$$ (eq:a_t)
+
+Equations {eq}`eq:a_t` constitute $T+1$ such budget constraints, one for each $t=0, 1, \ldots, T$.
+
+Given a sequence $y$ of non-financial incomes, a large set of pairs $(a, c)$ of (financial wealth, consumption) sequences satisfy the sequence of budget constraints {eq}`eq:a_t`.
+
+Our model has the following logical flow.
+
+ * start with an exogenous non-financial income sequence $y$, an initial financial wealth $a_0$, and
+ a candidate consumption path $c$.
+
+ * use the system of equations {eq}`eq:a_t` for $t=0, \ldots, T$ to compute a path $a$ of financial wealth
+
+ * verify that $a_{T+1}$ satisfies the terminal wealth constraint $a_{T+1} \geq 0$.
+
+ * If it does, declare that the candidate path is **budget feasible**.
+
+ * if the candidate consumption path is not budget feasible, propose a less greedy consumption path and start over
+
+Below, we'll describe how to execute these steps using linear algebra -- matrix inversion and multiplication.
+
+The above procedure seems like a sensible way to find "budget-feasible" consumption paths $c$, i.e., paths that are consistent
+with the exogenous non-financial income stream $y$, the initial financial asset level $a_0$, and the terminal asset level $a_{T+1}$.
+
+In general, there are **many** budget feasible consumption paths $c$.
+
+Among all budget-feasible consumption paths, which one should a consumer want?
+
+
+To answer this question, we shall eventually evaluate alternative budget feasible consumption paths $c$ using the following utility functional or **welfare criterion**:
+
+```{math}
+:label: welfare
+
+W = \sum_{t=0}^T \beta^t (g_1 c_t - \frac{g_2}{2} c_t^2 )
+```
+
+where $g_1 > 0, g_2 > 0$.
+
+When $\beta R \approx 1$, the fact that the utility function $g_1 c_t - \frac{g_2}{2} c_t^2$ has diminishing marginal utility imparts a preference for consumption that is very smooth.
+
+Indeed, we shall see that when $\beta R = 1$ (a condition assumed by Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`), criterion {eq}`welfare` assigns higher welfare to smoother consumption paths.
+
+By **smoother** we mean as close as possible to being constant over time.
+
+The preference for smooth consumption paths that is built into the model gives it the name "consumption-smoothing model".
+
+Let's dive in and do some calculations that will help us understand how the model works.
+
+Here we use default parameters $R = 1.05$, $g_1 = 1$, $g_2 = 1/2$, and $T = 65$.
+
+We create a Python **namedtuple** to store these parameters with default values.
+
+```{code-cell} ipython3
+ConsumptionSmoothing = namedtuple("ConsumptionSmoothing",
+ ["R", "g1", "g2", "β_seq", "T"])
+
+def create_consumption_smoothing_model(R=1.05, g1=1, g2=1/2, T=65):
+ β = 1/R
+ β_seq = np.array([β**i for i in range(T+1)])
+ return ConsumptionSmoothing(R, g1, g2,
+ β_seq, T)
+```
+
+
+## Friedman-Hall consumption-smoothing model
+
+A key object is what Milton Friedman called "human" or "non-financial" wealth at time $0$:
+
+
+$$
+h_0 \equiv \sum_{t=0}^T R^{-t} y_t = \begin{bmatrix} 1 & R^{-1} & \cdots & R^{-T} \end{bmatrix}
+\begin{bmatrix} y_0 \cr y_1 \cr \vdots \cr y_T \end{bmatrix}
+$$
+
+Human or non-financial wealth at time $0$ is evidently just the present value of the consumer's non-financial income stream $y$.
+
+Formally it very much resembles the asset price that we computed in this QuantEcon lecture {doc}`present values `.
+
+Indeed, this is why Milton Friedman called it "human capital".
+
+By iterating on equation {eq}`eq:a_t` and imposing the terminal condition
+
+$$
+a_{T+1} = 0,
+$$
+
+it is possible to convert a sequence of budget constraints {eq}`eq:a_t` into a single intertemporal constraint
+
+$$
+\sum_{t=0}^T R^{-t} c_t = a_0 + h_0.
+$$ (eq:budget_intertemp)
+
+Equation {eq}`eq:budget_intertemp` says that the present value of the consumption stream equals the sum of financial and non-financial (or human) wealth.
+
+Robert Hall {cite}`Hall1978` showed that when $\beta R = 1$, a condition Milton Friedman had also assumed, it is "optimal" for a consumer to smooth consumption by setting
+
+$$
+c_t = c_0 \quad t =0, 1, \ldots, T
+$$
+
+(Later we'll present a "variational argument" that shows that this constant path maximizes
+criterion {eq}`welfare` when $\beta R =1$.)
+
+In this case, we can use the intertemporal budget constraint to write
+
+$$
+c_t = c_0 = \left(\sum_{t=0}^T R^{-t}\right)^{-1} (a_0 + h_0), \quad t= 0, 1, \ldots, T.
+$$ (eq:conssmoothing)
+
+Equation {eq}`eq:conssmoothing` is the consumption-smoothing model in a nutshell.
+
+
+## Mechanics of consumption-smoothing model
+
+As promised, we'll provide step-by-step instructions on how to use linear algebra, readily implemented in Python, to compute all objects in play in the consumption-smoothing model.
+
+In the calculations below, we'll set default values of $R > 1$, e.g., $R = 1.05$, and $\beta = R^{-1}$.
+
+### Step 1
+
+For a $(T+1) \times 1$ vector $y$, use matrix algebra to compute $h_0$
+
+$$
+h_0 = \sum_{t=0}^T R^{-t} y_t = \begin{bmatrix} 1 & R^{-1} & \cdots & R^{-T} \end{bmatrix}
+\begin{bmatrix} y_0 \cr y_1 \cr \vdots \cr y_T \end{bmatrix}
+$$
+
+### Step 2
+
+Compute an time $0$ consumption $c_0 $ :
+
+$$
+c_t = c_0 = \left( \frac{1 - R^{-1}}{1 - R^{-(T+1)}} \right) (a_0 + \sum_{t=0}^T R^{-t} y_t ) , \quad t = 0, 1, \ldots, T
+$$
+
+### Step 3
+
+Use the system of equations {eq}`eq:a_t` for $t=0, \ldots, T$ to compute a path $a$ of financial wealth.
+
+To do this, we translate that system of difference equations into a single matrix equation as follows:
+
+
+$$
+\begin{bmatrix}
+1 & 0 & 0 & \cdots & 0 & 0 & 0 \cr
+-R & 1 & 0 & \cdots & 0 & 0 & 0 \cr
+0 & -R & 1 & \cdots & 0 & 0 & 0 \cr
+\vdots &\vdots & \vdots & \cdots & \vdots & \vdots & \vdots \cr
+0 & 0 & 0 & \cdots & -R & 1 & 0 \cr
+0 & 0 & 0 & \cdots & 0 & -R & 1
+\end{bmatrix}
+\begin{bmatrix} a_1 \cr a_2 \cr a_3 \cr \vdots \cr a_T \cr a_{T+1}
+\end{bmatrix}
+= R
+\begin{bmatrix} y_0 + a_0 - c_0 \cr y_1 - c_0 \cr y_2 - c_0 \cr \vdots\cr y_{T-1} - c_0 \cr y_T - c_0
+\end{bmatrix}
+$$
+
+Multiply both sides by the inverse of the matrix on the left side to compute
+
+$$
+ \begin{bmatrix} a_1 \cr a_2 \cr a_3 \cr \vdots \cr a_T \cr a_{T+1} \end{bmatrix}
+$$
+
+
+Because we have built into our calculations that the consumer leaves the model with exactly zero assets, just barely satisfying the
+terminal condition that $a_{T+1} \geq 0$, it should turn out that
+
+$$
+a_{T+1} = 0.
+$$
+
+
+Let's verify this with Python code.
+
+First we implement the model with `compute_optimal`
+
+```{code-cell} ipython3
+def compute_optimal(model, a0, y_seq):
+ R, T = model.R, model.T
+
+ # non-financial wealth
+ h0 = model.β_seq @ y_seq # since β = 1/R
+
+ # c0
+ c0 = (1 - 1/R) / (1 - (1/R)**(T+1)) * (a0 + h0)
+ c_seq = c0*np.ones(T+1)
+
+ # verify
+ A = np.diag(-R*np.ones(T), k=-1) + np.eye(T+1)
+ b = y_seq - c_seq
+ b[0] = b[0] + a0
+
+ a_seq = np.linalg.inv(A) @ b
+ a_seq = np.concatenate([[a0], a_seq])
+
+ return c_seq, a_seq, h0
+```
+
+We use an example where the consumer inherits $a_0<0$.
+
+This can be interpreted as a student debt.
+
+The non-financial process $\{y_t\}_{t=0}^{T}$ is constant and positive up to $t=45$ and then becomes zero afterward.
+
+The drop in non-financial income late in life reflects retirement from work.
+
+```{code-cell} ipython3
+# Financial wealth
+a0 = -2 # such as "student debt"
+
+# non-financial Income process
+y_seq = np.concatenate([np.ones(46), np.zeros(20)])
+
+cs_model = create_consumption_smoothing_model()
+c_seq, a_seq, h0 = compute_optimal(cs_model, a0, y_seq)
+
+print('check a_T+1=0:',
+ np.abs(a_seq[-1] - 0) <= 1e-8)
+```
+
+The graphs below show paths of non-financial income, consumption, and financial assets.
+
+```{code-cell} ipython3
+# Sequence Length
+T = cs_model.T
+
+plt.plot(range(T+1), y_seq, label='non-financial income')
+plt.plot(range(T+1), c_seq, label='consumption')
+plt.plot(range(T+2), a_seq, label='financial wealth')
+plt.plot(range(T+2), np.zeros(T+2), '--')
+
+plt.legend()
+plt.xlabel(r'$t$')
+plt.ylabel(r'$c_t,y_t,a_t$')
+plt.show()
+```
+
+Note that $a_{T+1} = 0$, as anticipated.
+
+We can evaluate welfare criterion {eq}`welfare`
+
+```{code-cell} ipython3
+def welfare(model, c_seq):
+ β_seq, g1, g2 = model.β_seq, model.g1, model.g2
+
+ u_seq = g1 * c_seq - g2/2 * c_seq**2
+ return β_seq @ u_seq
+
+print('Welfare:', welfare(cs_model, c_seq))
+```
+
+### Experiments
+
+In this section we describe how a consumption sequence would optimally respond to different sequences sequences of non-financial income.
+
+First we create a function `plot_cs` that generates graphs for different instances of the consumption-smoothing model `cs_model`.
+
+This will help us avoid rewriting code to plot outcomes for different non-financial income sequences.
+
+```{code-cell} ipython3
+def plot_cs(model, # consumption-smoothing model
+ a0, # initial financial wealth
+ y_seq # non-financial income process
+ ):
+
+ # Compute optimal consumption
+ c_seq, a_seq, h0 = compute_optimal(model, a0, y_seq)
+
+ # Sequence length
+ T = cs_model.T
+
+ # Generate plot
+ plt.plot(range(T+1), y_seq, label='non-financial income')
+ plt.plot(range(T+1), c_seq, label='consumption')
+ plt.plot(range(T+2), a_seq, label='financial wealth')
+ plt.plot(range(T+2), np.zeros(T+2), '--')
+
+ plt.legend()
+ plt.xlabel(r'$t$')
+ plt.ylabel(r'$c_t,y_t,a_t$')
+ plt.show()
+```
+
+In the experiments below, please study how consumption and financial asset sequences vary across different sequences for non-financial income.
+
+#### Experiment 1: one-time gain/loss
+
+We first assume a one-time windfall of $W_0$ in year 21 of the income sequence $y$.
+
+We'll make $W_0$ big - positive to indicate a one-time windfall, and negative to indicate a one-time "disaster".
+
+```{code-cell} ipython3
+# Windfall W_0 = 2.5
+y_seq_pos = np.concatenate([np.ones(21), np.array([2.5]), np.ones(24), np.zeros(20)])
+
+plot_cs(cs_model, a0, y_seq_pos)
+```
+
+```{code-cell} ipython3
+# Disaster W_0 = -2.5
+y_seq_neg = np.concatenate([np.ones(21), np.array([-2.5]), np.ones(24), np.zeros(20)])
+
+plot_cs(cs_model, a0, y_seq_neg)
+```
+
+#### Experiment 2: permanent wage gain/loss
+
+Now we assume a permanent increase in income of $W$ in year 21 of the $y$-sequence.
+
+Again we can study positive and negative cases
+
+```{code-cell} ipython3
+# Positive permanent income change W = 0.5 when t >= 21
+y_seq_pos = np.concatenate(
+ [np.ones(21), 1.5*np.ones(25), np.zeros(20)])
+
+plot_cs(cs_model, a0, y_seq_pos)
+```
+
+```{code-cell} ipython3
+# Negative permanent income change W = -0.5 when t >= 21
+y_seq_neg = np.concatenate(
+ [np.ones(21), .5*np.ones(25), np.zeros(20)])
+
+plot_cs(cs_model, a0, y_seq_neg)
+```
+
+#### Experiment 3: a late starter
+
+Now we simulate a $y$ sequence in which a person gets zero for 46 years, and then works and gets 1 for the last 20 years of life (a "late starter")
+
+```{code-cell} ipython3
+# Late starter
+y_seq_late = np.concatenate(
+ [np.zeros(46), np.ones(20)])
+
+plot_cs(cs_model, a0, y_seq_late)
+```
+
+#### Experiment 4: geometric earner
+
+Now we simulate a geometric $y$ sequence in which a person gets $y_t = \lambda^t y_0$ in first 46 years.
+
+We first experiment with $\lambda = 1.05$
+
+```{code-cell} ipython3
+# Geometric earner parameters where λ = 1.05
+λ = 1.05
+y_0 = 1
+t_max = 46
+
+# Generate geometric y sequence
+geo_seq = λ ** np.arange(t_max) * y_0
+y_seq_geo = np.concatenate(
+ [geo_seq, np.zeros(20)])
+
+plot_cs(cs_model, a0, y_seq_geo)
+```
+
+Now we show the behavior when $\lambda = 0.95$
+
+```{code-cell} ipython3
+λ = 0.95
+
+geo_seq = λ ** np.arange(t_max) * y_0
+y_seq_geo = np.concatenate(
+ [geo_seq, np.zeros(20)])
+
+plot_cs(cs_model, a0, y_seq_geo)
+```
+
+What happens when $\lambda$ is negative
+
+```{code-cell} ipython3
+λ = -0.95
+
+geo_seq = λ ** np.arange(t_max) * y_0
+y_seq_geo = np.concatenate(
+ [geo_seq, np.zeros(20)])
+
+plot_cs(cs_model, a0, y_seq_geo)
+```
+
+
+### Feasible consumption variations
+
+We promised to justify our claim that a constant consumption play $c_t = c_0$ for all
+$t$ is optimal.
+
+Let's do that now.
+
+The approach we'll take is an elementary example of the "calculus of variations".
+
+Let's dive in and see what the key idea is.
+
+To explore what types of consumption paths are welfare-improving, we shall create an **admissible consumption path variation sequence** $\{v_t\}_{t=0}^T$
+that satisfies
+
+$$
+\sum_{t=0}^T R^{-t} v_t = 0
+$$
+
+This equation says that the **present value** of admissible consumption path variations must be zero.
+
+So once again, we encounter a formula for the present value of an "asset":
+
+ * we require that the present value of consumption path variations be zero.
+
+Here we'll restrict ourselves to a two-parameter class of admissible consumption path variations
+of the form
+
+$$
+v_t = \xi_1 \phi^t - \xi_0
+$$
+
+We say two and not three-parameter class because $\xi_0$ will be a function of $(\phi, \xi_1; R)$ that guarantees that the variation sequence is feasible.
+
+Let's compute that function.
+
+We require
+
+$$
+\sum_{t=0}^T R^{-t}\left[ \xi_1 \phi^t - \xi_0 \right] = 0
+$$
+
+which implies that
+
+$$
+\xi_1 \sum_{t=0}^T \phi_t R^{-t} - \xi_0 \sum_{t=0}^T R^{-t} = 0
+$$
+
+which implies that
+
+$$
+\xi_1 \frac{1 - (\phi R^{-1})^{T+1}}{1 - \phi R^{-1}} - \xi_0 \frac{1 - R^{-(T+1)}}{1-R^{-1} } =0
+$$
+
+which implies that
+
+$$
+\xi_0 = \xi_0(\phi, \xi_1; R) = \xi_1 \left(\frac{1 - R^{-1}}{1 - R^{-(T+1)}}\right) \left(\frac{1 - (\phi R^{-1})^{T+1}}{1 - \phi R^{-1}}\right)
+$$
+
+This is our formula for $\xi_0$.
+
+**Key Idea:** if $c^o$ is a budget-feasible consumption path, then so is $c^o + v$,
+where $v$ is a budget-feasible variation.
+
+Given $R$, we thus have a two parameter class of budget feasible variations $v$ that we can use
+to compute alternative consumption paths, then evaluate their welfare.
+
+Now let's compute and plot consumption path variations
+
+```{code-cell} ipython3
+def compute_variation(model, ξ1, ϕ, a0, y_seq, verbose=1):
+ R, T, β_seq = model.R, model.T, model.β_seq
+
+ ξ0 = ξ1*((1 - 1/R) / (1 - (1/R)**(T+1))) * ((1 - (ϕ/R)**(T+1)) / (1 - ϕ/R))
+ v_seq = np.array([(ξ1*ϕ**t - ξ0) for t in range(T+1)])
+
+ if verbose == 1:
+ print('check feasible:', np.isclose(β_seq @ v_seq, 0)) # since β = 1/R
+
+ c_opt, _, _ = compute_optimal(model, a0, y_seq)
+ cvar_seq = c_opt + v_seq
+
+ return cvar_seq
+```
+
+
+We visualize variations for $\xi_1 \in \{.01, .05\}$ and $\phi \in \{.95, 1.02\}$
+
+```{code-cell} ipython3
+fig, ax = plt.subplots()
+
+ξ1s = [.01, .05]
+ϕs= [.95, 1.02]
+colors = {.01: 'tab:blue', .05: 'tab:green'}
+
+params = np.array(np.meshgrid(ξ1s, ϕs)).T.reshape(-1, 2)
+
+for i, param in enumerate(params):
+ ξ1, ϕ = param
+ print(f'variation {i}: ξ1={ξ1}, ϕ={ϕ}')
+ cvar_seq = compute_variation(model=cs_model,
+ ξ1=ξ1, ϕ=ϕ, a0=a0,
+ y_seq=y_seq)
+ print(f'welfare={welfare(cs_model, cvar_seq)}')
+ print('-'*64)
+ if i % 2 == 0:
+ ls = '-.'
+ else:
+ ls = '-'
+ ax.plot(range(T+1), cvar_seq, ls=ls,
+ color=colors[ξ1],
+ label=fr'$\xi_1 = {ξ1}, \phi = {ϕ}$')
+
+plt.plot(range(T+1), c_seq,
+ color='orange', label=r'Optimal $\vec{c}$ ')
+
+plt.legend()
+plt.xlabel(r'$t$')
+plt.ylabel(r'$c_t$')
+plt.show()
+```
+
+
+We can even use the Python `np.gradient` command to compute derivatives of welfare with respect to our two parameters.
+
+We are teaching the key idea beneath the **calculus of variations**.
+
+First, we define the welfare with respect to $\xi_1$ and $\phi$
+
+```{code-cell} ipython3
+def welfare_rel(ξ1, ϕ):
+ """
+ Compute welfare of variation sequence
+ for given ϕ, ξ1 with a consumption-smoothing model
+ """
+
+ cvar_seq = compute_variation(cs_model, ξ1=ξ1,
+ ϕ=ϕ, a0=a0,
+ y_seq=y_seq,
+ verbose=0)
+ return welfare(cs_model, cvar_seq)
+
+# Vectorize the function to allow array input
+welfare_vec = np.vectorize(welfare_rel)
+```
+
+
+Then we can visualize the relationship between welfare and $\xi_1$ and compute its derivatives
+
+```{code-cell} ipython3
+ξ1_arr = np.linspace(-0.5, 0.5, 20)
+
+plt.plot(ξ1_arr, welfare_vec(ξ1_arr, 1.02))
+plt.ylabel('welfare')
+plt.xlabel(r'$\xi_1$')
+plt.show()
+
+welfare_grad = welfare_vec(ξ1_arr, 1.02)
+welfare_grad = np.gradient(welfare_grad)
+plt.plot(ξ1_arr, welfare_grad)
+plt.ylabel('derivative of welfare')
+plt.xlabel(r'$\xi_1$')
+plt.show()
+```
+
+
+The same can be done on $\phi$
+
+```{code-cell} ipython3
+ϕ_arr = np.linspace(-0.5, 0.5, 20)
+
+plt.plot(ξ1_arr, welfare_vec(0.05, ϕ_arr))
+plt.ylabel('welfare')
+plt.xlabel(r'$\phi$')
+plt.show()
+
+welfare_grad = welfare_vec(0.05, ϕ_arr)
+welfare_grad = np.gradient(welfare_grad)
+plt.plot(ξ1_arr, welfare_grad)
+plt.ylabel('derivative of welfare')
+plt.xlabel(r'$\phi$')
+plt.show()
+```
+
+## Wrapping up the consumption-smoothing model
+
+The consumption-smoothing model of Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`) is a cornerstone of modern macro that has important ramifications for the size of the Keynesian "fiscal policy multiplier" described briefly in
+QuantEcon lecture {doc}`geometric series `.
+
+In particular, it **lowers** the government expenditure multiplier relative to one implied by
+the original Keynesian consumption function presented in {doc}`geometric series `.
+
+Friedman's work opened the door to an enlightening literature on the aggregate consumption function and associated government expenditure multipliers that
+remains active today.
+
+
+## Appendix: solving difference equations with linear algebra
+
+In the preceding sections we have used linear algebra to solve a consumption-smoothing model.
+
+The same tools from linear algebra -- matrix multiplication and matrix inversion -- can be used to study many other dynamic models.
+
+We'll conclude this lecture by giving a couple of examples.
+
+We'll describe a useful way of representing and "solving" linear difference equations.
+
+To generate some $y$ vectors, we'll just write down a linear difference equation
+with appropriate initial conditions and then use linear algebra to solve it.
+
+### First-order difference equation
+
+We'll start with a first-order linear difference equation for $\{y_t\}_{t=0}^T$:
+
+$$
+y_{t} = \lambda y_{t-1}, \quad t = 1, 2, \ldots, T
+$$
+
+where $y_0$ is a given initial condition.
+
+
+We can cast this set of $T$ equations as a single matrix equation
+
+$$
+\begin{bmatrix}
+1 & 0 & 0 & \cdots & 0 & 0 \cr
+-\lambda & 1 & 0 & \cdots & 0 & 0 \cr
+0 & -\lambda & 1 & \cdots & 0 & 0 \cr
+ \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr
+0 & 0 & 0 & \cdots & -\lambda & 1
+\end{bmatrix}
+\begin{bmatrix}
+y_1 \cr y_2 \cr y_3 \cr \vdots \cr y_T
+\end{bmatrix}
+=
+\begin{bmatrix}
+\lambda y_0 \cr 0 \cr 0 \cr \vdots \cr 0
+\end{bmatrix}
+$$ (eq:first_order_lin_diff)
+
+
+Multiplying both sides of {eq}`eq:first_order_lin_diff` by the inverse of the matrix on the left provides the solution
+
+```{math}
+:label: fst_ord_inverse
+
+\begin{bmatrix}
+y_1 \cr y_2 \cr y_3 \cr \vdots \cr y_T
+\end{bmatrix}
+=
+\begin{bmatrix}
+1 & 0 & 0 & \cdots & 0 & 0 \cr
+\lambda & 1 & 0 & \cdots & 0 & 0 \cr
+\lambda^2 & \lambda & 1 & \cdots & 0 & 0 \cr
+ \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr
+\lambda^{T-1} & \lambda^{T-2} & \lambda^{T-3} & \cdots & \lambda & 1
+\end{bmatrix}
+\begin{bmatrix}
+\lambda y_0 \cr 0 \cr 0 \cr \vdots \cr 0
+\end{bmatrix}
+```
+
+```{exercise}
+:label: consmooth_ex1
+
+To get {eq}`fst_ord_inverse`, we multiplied both sides of {eq}`eq:first_order_lin_diff` by the inverse of the matrix $A$. Please confirm that
+
+$$
+\begin{bmatrix}
+1 & 0 & 0 & \cdots & 0 & 0 \cr
+\lambda & 1 & 0 & \cdots & 0 & 0 \cr
+\lambda^2 & \lambda & 1 & \cdots & 0 & 0 \cr
+ \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr
+\lambda^{T-1} & \lambda^{T-2} & \lambda^{T-3} & \cdots & \lambda & 1
+\end{bmatrix}
+$$
+
+is the inverse of $A$ and check that $A A^{-1} = I$
+
+```
+
+### Second-order difference equation
+
+A second-order linear difference equation for $\{y_t\}_{t=0}^T$ is
+
+$$
+y_{t} = \lambda_1 y_{t-1} + \lambda_2 y_{t-2}, \quad t = 1, 2, \ldots, T
+$$
+
+where now $y_0$ and $y_{-1}$ are two given initial equations determined outside the model.
+
+As we did with the first-order difference equation, we can cast this set of $T$ equations as a single matrix equation
+
+$$
+\begin{bmatrix}
+1 & 0 & 0 & \cdots & 0 & 0 & 0 \cr
+-\lambda_1 & 1 & 0 & \cdots & 0 & 0 & 0 \cr
+-\lambda_2 & -\lambda_1 & 1 & \cdots & 0 & 0 & 0 \cr
+ \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr
+0 & 0 & 0 & \cdots & -\lambda_2 & -\lambda_1 & 1
+\end{bmatrix}
+\begin{bmatrix}
+y_1 \cr y_2 \cr y_3 \cr \vdots \cr y_T
+\end{bmatrix}
+=
+\begin{bmatrix}
+\lambda_1 y_0 + \lambda_2 y_{-1} \cr \lambda_2 y_0 \cr 0 \cr \vdots \cr 0
+\end{bmatrix}
+$$
+
+Multiplying both sides by inverse of the matrix on the left again provides the solution.
+
+```{exercise}
+:label: consmooth_ex2
+
+As an exercise, we ask you to represent and solve a **third-order linear difference equation**.
+How many initial conditions must you specify?
+```
diff --git a/content/lectures/eigen_I.ipynb b/book/_build/html/_sources/eigen_I.ipynb
similarity index 68%
rename from content/lectures/eigen_I.ipynb
rename to book/_build/html/_sources/eigen_I.ipynb
index 21b9468..4cf9ce0 100644
--- a/content/lectures/eigen_I.ipynb
+++ b/book/_build/html/_sources/eigen_I.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "d6cbeebc",
+ "id": "db81524a",
"metadata": {
"user_expressions": []
},
@@ -13,14 +13,9 @@
"```{index} single: Eigenvalues and Eigenvectors\n",
"```\n",
"\n",
- "```{contents} Contents\n",
- ":depth: 2\n",
- "```\n",
- "\n",
"## Overview\n",
"\n",
- "Eigenvalues and eigenvectors are a somewhat advanced topic in linear and\n",
- "matrix algebra.\n",
+ "Eigenvalues and eigenvectors are a relatively advanced topic in linear algebra.\n",
"\n",
"At the same time, these concepts are extremely useful for \n",
"\n",
@@ -30,17 +25,10 @@
"* machine learning\n",
"* and many other fields of science.\n",
"\n",
- "In this lecture we explain the basics of eigenvalues and eigenvectors, and\n",
- "state two very important results from linear algebra.\n",
- "\n",
- "The first is called the Neumann series theorem and the second is called the\n",
- "Perron-Frobenius theorem.\n",
+ "In this lecture we explain the basics of eigenvalues and eigenvectors and introduce the Neumann Series Lemma.\n",
"\n",
- "We will explain what these theorems tell us and how we can use them to\n",
- "understand the predictions of economic models.\n",
- "\n",
- "We assume in this lecture that students are familiar with matrices and\n",
- "understand the basics of matrix algebra.\n",
+ "We assume in this lecture that students are familiar with matrices\n",
+ " and understand {doc}`the basics of matrix algebra`.\n",
"\n",
"We will use the following imports:"
]
@@ -48,39 +36,35 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "5928f6e3",
+ "id": "8b155d43",
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"from numpy.linalg import matrix_power\n",
- "from matplotlib import cm\n",
"from matplotlib.lines import Line2D\n",
- "from mpl_toolkits.mplot3d import Axes3D\n",
"from matplotlib.patches import FancyArrowPatch\n",
"from mpl_toolkits.mplot3d import proj3d"
]
},
{
"cell_type": "markdown",
- "id": "94449a82",
- "metadata": {
- "user_expressions": []
- },
+ "id": "6f681f6e",
+ "metadata": {},
"source": [
"(matrices_as_transformation)=\n",
"## Matrices as transformations\n",
"\n",
"Let's start by discussing an important concept concerning matrices.\n",
"\n",
- "### Mapping vectors into vectors\n",
+ "### Mapping vectors to vectors\n",
"\n",
- "One way to think about a given matrix is as a rectangular collection of\n",
+ "One way to think about a matrix is as a rectangular collection of\n",
"numbers.\n",
"\n",
- "Another way to think about a matrix is as a **map** (i.e., as a function) that\n",
- "transforms vectors into new vectors.\n",
+ "Another way to think about a matrix is as a *map* (i.e., as a function) that\n",
+ "transforms vectors to new vectors.\n",
"\n",
"To understand the second point of view, suppose we multiply an $n \\times m$\n",
"matrix $A$ with an $m \\times 1$ column vector $x$ to obtain an $n \\times 1$\n",
@@ -91,26 +75,27 @@
"$$\n",
"\n",
"If we fix $A$ and consider different choices of $x$, we can understand $A$ as\n",
- "a map transforming $x$ into $Ax$.\n",
+ "a map transforming $x$ to $Ax$.\n",
"\n",
- "Because $A$ is $n \\times m$, it transforms $m$-vectors into $n$-vectors.\n",
+ "Because $A$ is $n \\times m$, it transforms $m$-vectors to $n$-vectors.\n",
"\n",
- "We can write this formally as $A \\colon \\mathbb{R}^m \\rightarrow \\mathbb{R}^n$ \n",
+ "We can write this formally as $A \\colon \\mathbb{R}^m \\rightarrow \\mathbb{R}^n$.\n",
"\n",
- "(You might argue that if $A$ is a function then we should write \n",
- "$A(x) = y$ rather than $Ax = y$ but the second notation is more conventional.)\n",
+ "You might argue that if $A$ is a function then we should write \n",
+ "$A(x) = y$ rather than $Ax = y$ but the second notation is more conventional.\n",
"\n",
"### Square matrices\n",
"\n",
"Let's restrict our discussion to square matrices.\n",
"\n",
- "In the above discussion, this means that $m=n$ and $A$ maps $\\mathbb R^n$ into\n",
+ "In the above discussion, this means that $m=n$ and $A$ maps $\\mathbb R^n$ to\n",
"itself.\n",
"\n",
- "To repeat, $A$ is an $n \\times n$ matrix that maps (or \"transforms\") a vector\n",
- "$x$ in $\\mathbb{R}^n$ into a new vector $y=Ax$ also in $\\mathbb{R}^n$.\n",
+ "This means $A$ is an $n \\times n$ matrix that maps (or \"transforms\") a vector\n",
+ "$x$ in $\\mathbb{R}^n$ to a new vector $y=Ax$ also in $\\mathbb{R}^n$.\n",
"\n",
- "Here's one example:\n",
+ "```{prf:example}\n",
+ ":label: eigen1_ex_sq\n",
"\n",
"$$\n",
" \\begin{bmatrix}\n",
@@ -136,8 +121,9 @@
" \\end{bmatrix}\n",
"$$\n",
"\n",
- "transforms the vector $x = \\begin{bmatrix} 1 \\\\ 3 \\end{bmatrix}$ into the vector\n",
+ "transforms the vector $x = \\begin{bmatrix} 1 \\\\ 3 \\end{bmatrix}$ to the vector\n",
"$y = \\begin{bmatrix} 5 \\\\ 2 \\end{bmatrix}$.\n",
+ "```\n",
"\n",
"Let's visualize this using Python:"
]
@@ -145,18 +131,18 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "e9e5f08e",
+ "id": "56adfb2d",
"metadata": {},
"outputs": [],
"source": [
- "A = np.array([[2, 1], \n",
+ "A = np.array([[2, 1],\n",
" [-1, 1]])"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "8229460b",
+ "id": "a4114d91",
"metadata": {},
"outputs": [],
"source": [
@@ -172,43 +158,44 @@
"\n",
"ax.set(xlim=(-2, 6), ylim=(-2, 4), aspect=1)\n",
"\n",
- "vecs = ((1, 3),(5, 2))\n",
- "c = ['r','black']\n",
+ "vecs = ((1, 3), (5, 2))\n",
+ "c = ['r', 'black']\n",
"for i, v in enumerate(vecs):\n",
" ax.annotate('', xy=v, xytext=(0, 0),\n",
" arrowprops=dict(color=c[i],\n",
" shrink=0,\n",
" alpha=0.7,\n",
" width=0.5))\n",
- " \n",
- "ax.text(0.2 + 1 , 0.2 + 3, 'x=$(1,3)$')\n",
- "ax.text(0.2 + 5 , 0.2 + 2, 'Ax=$(5,2)$')\n",
- " \n",
- "ax.annotate('', xy=(sqrt(10/29)* 5, sqrt(10/29) *2), xytext=(0, 0),\n",
- " arrowprops=dict(color='purple',\n",
- " shrink=0,\n",
- " alpha=0.7,\n",
- " width=0.5))\n",
"\n",
- "ax.annotate('',xy=(1,2/5),xytext=(1/3, 1),\n",
- " arrowprops={'arrowstyle':'->', 'connectionstyle':'arc3,rad=-0.3'}\n",
- " ,horizontalalignment='center')\n",
- "ax.text(0.8,0.8, f'θ',fontsize =14)\n",
+ "ax.text(0.2 + 1, 0.2 + 3, 'x=$(1,3)$')\n",
+ "ax.text(0.2 + 5, 0.2 + 2, 'Ax=$(5,2)$')\n",
+ "\n",
+ "ax.annotate('', xy=(sqrt(10/29) * 5, sqrt(10/29) * 2), xytext=(0, 0),\n",
+ " arrowprops=dict(color='purple',\n",
+ " shrink=0,\n",
+ " alpha=0.7,\n",
+ " width=0.5))\n",
+ "\n",
+ "ax.annotate('', xy=(1, 2/5), xytext=(1/3, 1),\n",
+ " arrowprops={'arrowstyle': '->',\n",
+ " 'connectionstyle': 'arc3,rad=-0.3'},\n",
+ " horizontalalignment='center')\n",
+ "ax.text(0.8, 0.8, f'θ', fontsize=14)\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
- "id": "8542f1bd",
+ "id": "6c349d5b",
"metadata": {
"user_expressions": []
},
"source": [
"One way to understand this transformation is that $A$ \n",
"\n",
- "* first rotates $x$ by some angle $\\theta$ \n",
- "* and then scales it by some scalar $\\gamma$ to obtain the image $y$ of $x$.\n",
+ "* first rotates $x$ by some angle $\\theta$ and\n",
+ "* then scales it by some scalar $\\gamma$ to obtain the image $y$ of $x$.\n",
"\n",
"\n",
"\n",
@@ -222,17 +209,17 @@
"We consider how a given matrix transforms \n",
"\n",
"* a grid of points and \n",
- "* a set of points located on the unit circle in $\\mathbb{R}^2$\n",
+ "* a set of points located on the unit circle in $\\mathbb{R}^2$.\n",
"\n",
"To build the transformations we will use two functions, called `grid_transform` and `circle_transform`.\n",
"\n",
- "Each of these functions visualizes the action of a given $2 \\times 2$ matrix $A$."
+ "Each of these functions visualizes the actions of a given $2 \\times 2$ matrix $A$."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "049b1d5a",
+ "id": "da8eb89d",
"metadata": {
"tags": [
"hide-input"
@@ -246,16 +233,17 @@
" b = 1/4 + x/16\n",
" return (r, g, b)\n",
"\n",
- "def grid_transform(A = np.array([[1, -1], [1, 1]])):\n",
+ "\n",
+ "def grid_transform(A=np.array([[1, -1], [1, 1]])):\n",
" xvals = np.linspace(-4, 4, 9)\n",
" yvals = np.linspace(-3, 3, 7)\n",
" xygrid = np.column_stack([[x, y] for x in xvals for y in yvals])\n",
" uvgrid = A @ xygrid\n",
- " \n",
+ "\n",
" colors = list(map(colorizer, xygrid[0], xygrid[1]))\n",
- " \n",
- " figure, ax = plt.subplots(1,2, figsize = (10,5))\n",
- " \n",
+ "\n",
+ " fig, ax = plt.subplots(1, 2, figsize=(10, 5))\n",
+ "\n",
" for axes in ax:\n",
" axes.set(xlim=(-11, 11), ylim=(-11, 11))\n",
" axes.set_xticks([])\n",
@@ -264,25 +252,26 @@
" axes.spines[spine].set_position('zero')\n",
" for spine in ['right', 'top']:\n",
" axes.spines[spine].set_color('none')\n",
- " \n",
+ "\n",
" # Plot x-y grid points\n",
" ax[0].scatter(xygrid[0], xygrid[1], s=36, c=colors, edgecolor=\"none\")\n",
- " #ax[0].grid(True)\n",
- " #ax[0].axis(\"equal\")\n",
+ " # ax[0].grid(True)\n",
+ " # ax[0].axis(\"equal\")\n",
" ax[0].set_title(\"points $x_1, x_2, \\cdots, x_k$\")\n",
- " \n",
+ "\n",
" # Plot transformed grid points\n",
" ax[1].scatter(uvgrid[0], uvgrid[1], s=36, c=colors, edgecolor=\"none\")\n",
- " #ax[1].grid(True)\n",
- " #ax[1].axis(\"equal\")\n",
+ " # ax[1].grid(True)\n",
+ " # ax[1].axis(\"equal\")\n",
" ax[1].set_title(\"points $Ax_1, Ax_2, \\cdots, Ax_k$\")\n",
- " \n",
+ "\n",
" plt.show()\n",
"\n",
- "def circle_transform(A = np.array([[-1, 2], [0, 1]])):\n",
- " \n",
- " figure, ax = plt.subplots(1,2, figsize = (10,5))\n",
- " \n",
+ "\n",
+ "def circle_transform(A=np.array([[-1, 2], [0, 1]])):\n",
+ "\n",
+ " fig, ax = plt.subplots(1, 2, figsize=(10, 5))\n",
+ "\n",
" for axes in ax:\n",
" axes.set(xlim=(-4, 4), ylim=(-4, 4))\n",
" axes.set_xticks([])\n",
@@ -291,41 +280,44 @@
" axes.spines[spine].set_position('zero')\n",
" for spine in ['right', 'top']:\n",
" axes.spines[spine].set_color('none')\n",
- " \n",
- " θ = np.linspace( 0 , 2 * np.pi , 150) \n",
+ "\n",
+ " θ = np.linspace(0, 2 * np.pi, 150)\n",
" r = 1\n",
- " \n",
+ "\n",
" θ_1 = np.empty(12)\n",
" for i in range(12):\n",
" θ_1[i] = 2 * np.pi * (i/12)\n",
- " \n",
- " x = r * np.cos(θ) \n",
+ "\n",
+ " x = r * np.cos(θ)\n",
" y = r * np.sin(θ)\n",
" a = r * np.cos(θ_1)\n",
" b = r * np.sin(θ_1)\n",
- " a_1 = a.reshape(1,-1)\n",
- " b_1 = b.reshape(1,-1)\n",
+ " a_1 = a.reshape(1, -1)\n",
+ " b_1 = b.reshape(1, -1)\n",
" colors = list(map(colorizer, a, b))\n",
- " ax[0].plot(x, y, color = 'black', zorder=1)\n",
- " ax[0].scatter(a_1,b_1, c = colors, alpha = 1, s = 60, edgecolors = 'black', zorder =2)\n",
+ " ax[0].plot(x, y, color='black', zorder=1)\n",
+ " ax[0].scatter(a_1, b_1, c=colors, alpha=1, s=60,\n",
+ " edgecolors='black', zorder=2)\n",
" ax[0].set_title(\"unit circle in $\\mathbb{R}^2$\")\n",
- " \n",
- " x1= x.reshape(1,-1)\n",
+ "\n",
+ " x1 = x.reshape(1, -1)\n",
" y1 = y.reshape(1, -1)\n",
- " ab = np.concatenate((a_1,b_1), axis=0)\n",
+ " ab = np.concatenate((a_1, b_1), axis=0)\n",
" transformed_ab = A @ ab\n",
- " transformed_circle_input = np.concatenate((x1,y1), axis=0)\n",
+ " transformed_circle_input = np.concatenate((x1, y1), axis=0)\n",
" transformed_circle = A @ transformed_circle_input\n",
- " ax[1].plot(transformed_circle[0,:], transformed_circle[1,:], color = 'black', zorder= 1) \n",
- " ax[1].scatter(transformed_ab[0,:],transformed_ab[1:,], color = colors, alpha = 1, s = 60, edgecolors = 'black', zorder =2)\n",
+ " ax[1].plot(transformed_circle[0, :],\n",
+ " transformed_circle[1, :], color='black', zorder=1)\n",
+ " ax[1].scatter(transformed_ab[0, :], transformed_ab[1:,],\n",
+ " color=colors, alpha=1, s=60, edgecolors='black', zorder=2)\n",
" ax[1].set_title(\"transformed circle\")\n",
- " \n",
+ "\n",
" plt.show()"
]
},
{
"cell_type": "markdown",
- "id": "8b2cd59e",
+ "id": "84158333",
"metadata": {
"user_expressions": []
},
@@ -350,11 +342,11 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "16cb774a",
+ "id": "7960b7af",
"metadata": {},
"outputs": [],
"source": [
- "A = np.array([[3 ,0], #scaling by 3 in both directions\n",
+ "A = np.array([[3, 0], # scaling by 3 in both directions\n",
" [0, 3]])\n",
"grid_transform(A)\n",
"circle_transform(A)"
@@ -362,7 +354,7 @@
},
{
"cell_type": "markdown",
- "id": "be179291",
+ "id": "32285232",
"metadata": {
"user_expressions": []
},
@@ -385,7 +377,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "476cd58a",
+ "id": "27f88a7f",
"metadata": {},
"outputs": [],
"source": [
@@ -397,7 +389,7 @@
},
{
"cell_type": "markdown",
- "id": "e1a80b86",
+ "id": "9de1d252",
"metadata": {
"user_expressions": []
},
@@ -420,11 +412,11 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "6faf4397",
+ "id": "1418c1a3",
"metadata": {},
"outputs": [],
"source": [
- "θ = np.pi/4 #45 degree clockwise rotation\n",
+ "θ = np.pi/4 # 45 degree clockwise rotation\n",
"A = np.array([[np.cos(θ), np.sin(θ)],\n",
" [-np.sin(θ), np.cos(θ)]])\n",
"grid_transform(A)"
@@ -432,7 +424,7 @@
},
{
"cell_type": "markdown",
- "id": "e3ee61c8",
+ "id": "604a12d3",
"metadata": {
"user_expressions": []
},
@@ -453,7 +445,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "4abddde1",
+ "id": "b6de4fc7",
"metadata": {},
"outputs": [],
"source": [
@@ -463,7 +455,7 @@
},
{
"cell_type": "markdown",
- "id": "824b2d9f",
+ "id": "ecd244dd",
"metadata": {
"user_expressions": []
},
@@ -584,10 +576,10 @@
"\n",
"Thus the matrix product $AB$ is the\n",
"[composition](https://en.wikipedia.org/wiki/Function_composition) of the\n",
- "matrix transformations $A$ and $B$.\n",
+ "matrix transformations $A$ and $B$\n",
"\n",
- "(To compose the transformations, first apply transformation $B$ and then\n",
- "transformation $A$.)\n",
+ "This means first apply transformation $B$ and then\n",
+ "transformation $A$.\n",
"\n",
"When we matrix multiply an $n \\times m$ matrix $A$ with an $m \\times k$ matrix\n",
"$B$ the obtained matrix product is an $n \\times k$ matrix $AB$.\n",
@@ -597,7 +589,7 @@
"transforms $\\mathbb{R}^k$ to $\\mathbb{R}^n$.\n",
"\n",
"Viewing matrix multiplication as composition of maps helps us\n",
- "understand why, under matrix multiplication, $AB$ is not generally equal to $BA$.\n",
+ "understand why, under matrix multiplication, $AB$ is generally not equal to $BA$.\n",
"\n",
"(After all, when we compose functions, the order usually matters.)\n",
"\n",
@@ -614,7 +606,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "8815b4ca",
+ "id": "af0b0d1b",
"metadata": {
"tags": [
"hide-input"
@@ -622,17 +614,18 @@
},
"outputs": [],
"source": [
- "def grid_composition_transform(A = np.array([[1, -1], [1, 1]]), B = np.array([[1, -1], [1, 1]])):\n",
+ "def grid_composition_transform(A=np.array([[1, -1], [1, 1]]),\n",
+ " B=np.array([[1, -1], [1, 1]])):\n",
" xvals = np.linspace(-4, 4, 9)\n",
" yvals = np.linspace(-3, 3, 7)\n",
" xygrid = np.column_stack([[x, y] for x in xvals for y in yvals])\n",
" uvgrid = B @ xygrid\n",
" abgrid = A @ uvgrid\n",
- " \n",
+ "\n",
" colors = list(map(colorizer, xygrid[0], xygrid[1]))\n",
- " \n",
- " figure, ax = plt.subplots(1,3, figsize = (15,5))\n",
- " \n",
+ "\n",
+ " fig, ax = plt.subplots(1, 3, figsize=(15, 5))\n",
+ "\n",
" for axes in ax:\n",
" axes.set(xlim=(-12, 12), ylim=(-12, 12))\n",
" axes.set_xticks([])\n",
@@ -641,16 +634,16 @@
" axes.spines[spine].set_position('zero')\n",
" for spine in ['right', 'top']:\n",
" axes.spines[spine].set_color('none')\n",
- " \n",
+ "\n",
" # Plot grid points\n",
" ax[0].scatter(xygrid[0], xygrid[1], s=36, c=colors, edgecolor=\"none\")\n",
" ax[0].set_title(\"points $x_1, x_2, \\cdots, x_k$\")\n",
- " \n",
+ "\n",
" # Plot intermediate grid points\n",
" ax[1].scatter(uvgrid[0], uvgrid[1], s=36, c=colors, edgecolor=\"none\")\n",
" ax[1].set_title(\"points $Bx_1, Bx_2, \\cdots, Bx_k$\")\n",
- " \n",
- " #Plot transformed grid points\n",
+ "\n",
+ " # Plot transformed grid points\n",
" ax[2].scatter(abgrid[0], abgrid[1], s=36, c=colors, edgecolor=\"none\")\n",
" ax[2].set_title(\"points $ABx_1, ABx_2, \\cdots, ABx_k$\")\n",
"\n",
@@ -660,13 +653,10 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "6c98392e",
+ "id": "e050bf20",
"metadata": {},
"outputs": [],
"source": [
- "θ = np.pi/2 \n",
- "#B = np.array([[np.cos(θ), np.sin(θ)],\n",
- "# [-np.sin(θ), np.cos(θ)]])\n",
"A = np.array([[0, 1], # 90 degree clockwise rotation\n",
" [-1, 0]])\n",
"B = np.array([[1, 2], # shear along x-axis\n",
@@ -675,7 +665,7 @@
},
{
"cell_type": "markdown",
- "id": "4bfe7abf",
+ "id": "6ce0a196",
"metadata": {
"user_expressions": []
},
@@ -686,16 +676,16 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "3d3dae0b",
+ "id": "b26383d3",
"metadata": {},
"outputs": [],
"source": [
- "grid_composition_transform(A,B) #transformation AB"
+ "grid_composition_transform(A, B) # transformation AB"
]
},
{
"cell_type": "markdown",
- "id": "feaeb751",
+ "id": "8abaf846",
"metadata": {
"user_expressions": []
},
@@ -706,25 +696,25 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "601e19c4",
+ "id": "7f1a2ed9",
"metadata": {},
"outputs": [],
"source": [
- "grid_composition_transform(B,A) #transformation BA"
+ "grid_composition_transform(B,A) # transformation BA"
]
},
{
"cell_type": "markdown",
- "id": "dadc8c0d",
+ "id": "66de6985",
"metadata": {
"user_expressions": []
},
"source": [
- "It is quite evident that the transformation $AB$ is not the same as the transformation $BA$.\n",
+ "It is evident that the transformation $AB$ is not the same as the transformation $BA$.\n",
"\n",
"## Iterating on a fixed map\n",
"\n",
- "In economics (and especially in dynamic modeling), we often are interested in\n",
+ "In economics (and especially in dynamic modeling), we are often interested in\n",
"analyzing behavior where we repeatedly apply a fixed matrix.\n",
"\n",
"For example, given a vector $v$ and a matrix $A$, we are interested in\n",
@@ -733,7 +723,7 @@
"$$ \n",
" v, \\quad\n",
" Av, \\quad\n",
- " AAv = A^2v, \\ldots\n",
+ " AAv = A^2v, \\quad \\ldots\n",
"$$\n",
"\n",
"Let's first see examples of a sequence of iterates $(A^k v)_{k \\geq 0}$ under\n",
@@ -745,17 +735,17 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "f71edda3",
+ "id": "23fcc0a7",
"metadata": {},
"outputs": [],
"source": [
- "def plot_series(B, v, n):\n",
- " \n",
- " A = np.array([[1, -1],\n",
+ "def plot_series(A, v, n):\n",
+ "\n",
+ " B = np.array([[1, -1],\n",
" [1, 0]])\n",
- " \n",
- " figure, ax = plt.subplots()\n",
- " \n",
+ "\n",
+ " fig, ax = plt.subplots()\n",
+ "\n",
" ax.set(xlim=(-4, 4), ylim=(-4, 4))\n",
" ax.set_xticks([])\n",
" ax.set_yticks([])\n",
@@ -763,54 +753,55 @@
" ax.spines[spine].set_position('zero')\n",
" for spine in ['right', 'top']:\n",
" ax.spines[spine].set_color('none')\n",
- " \n",
- " θ = np.linspace( 0 , 2 * np.pi , 150) \n",
+ "\n",
+ " θ = np.linspace(0, 2 * np.pi, 150)\n",
" r = 2.5\n",
- " x = r * np.cos(θ) \n",
+ " x = r * np.cos(θ)\n",
" y = r * np.sin(θ)\n",
- " x1 = x.reshape(1,-1)\n",
+ " x1 = x.reshape(1, -1)\n",
" y1 = y.reshape(1, -1)\n",
- " xy = np.concatenate((x1,y1), axis=0)\n",
- " \n",
- " ellipse = A @ xy\n",
- " ax.plot(ellipse[0,:], ellipse[1,:], color = 'black', linestyle = (0, (5,10)), linewidth = 0.5)\n",
- " \n",
- " colors = plt.cm.rainbow(np.linspace(0,1,20))# Initialize holder for trajectories\n",
- " \n",
+ " xy = np.concatenate((x1, y1), axis=0)\n",
+ "\n",
+ " ellipse = B @ xy\n",
+ " ax.plot(ellipse[0, :], ellipse[1, :], color='black',\n",
+ " linestyle=(0, (5, 10)), linewidth=0.5)\n",
+ "\n",
+ " # Initialize holder for trajectories\n",
+ " colors = plt.cm.rainbow(np.linspace(0, 1, 20))\n",
+ "\n",
" for i in range(n):\n",
- " iteration = matrix_power(B, i) @ v\n",
+ " iteration = matrix_power(A, i) @ v\n",
" v1 = iteration[0]\n",
" v2 = iteration[1]\n",
" ax.scatter(v1, v2, color=colors[i])\n",
" if i == 0:\n",
" ax.text(v1+0.25, v2, f'$v$')\n",
- " if i == 1:\n",
+ " elif i == 1:\n",
" ax.text(v1+0.25, v2, f'$Av$')\n",
- " if 1< i < 4:\n",
+ " elif 1 < i < 4:\n",
" ax.text(v1+0.25, v2, f'$A^{i}v$')\n",
- " \n",
" plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "4cd1a08b",
+ "id": "c0b488c5",
"metadata": {},
"outputs": [],
"source": [
- "B = np.array([[sqrt(3) + 1, -2],\n",
+ "A = np.array([[sqrt(3) + 1, -2],\n",
" [1, sqrt(3) - 1]])\n",
- "B = (1/(2*sqrt(2))) * B\n",
+ "A = (1/(2*sqrt(2))) * A\n",
"v = (-3, -3)\n",
"n = 12\n",
"\n",
- "plot_series(B, v, n)"
+ "plot_series(A, v, n)"
]
},
{
"cell_type": "markdown",
- "id": "f4c53250",
+ "id": "f79030ad",
"metadata": {
"user_expressions": []
},
@@ -823,7 +814,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "e469f1a2",
+ "id": "6778314c",
"metadata": {},
"outputs": [],
"source": [
@@ -838,7 +829,7 @@
},
{
"cell_type": "markdown",
- "id": "5323eca7",
+ "id": "fbc39ab7",
"metadata": {
"user_expressions": []
},
@@ -852,7 +843,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "ad8a5f31",
+ "id": "c4bf654b",
"metadata": {},
"outputs": [],
"source": [
@@ -867,7 +858,7 @@
},
{
"cell_type": "markdown",
- "id": "72f7f91b",
+ "id": "293868d7",
"metadata": {
"user_expressions": []
},
@@ -893,13 +884,14 @@
"\n",
"Let $A$ be an $n \\times n$ square matrix.\n",
"\n",
- "If $\\lambda$ is scalar and $v$ is a non-zero $n$-vector such that\n",
+ "If $\\lambda$ is scalar and $v$ is a non-zero $n$-vector such that\n",
"\n",
"$$\n",
- "A v = \\lambda v\n",
+ "A v = \\lambda v.\n",
"$$\n",
"\n",
- "then we say that $\\lambda$ is an *eigenvalue* of $A$, and $v$ is an *eigenvector*.\n",
+ "\n",
+ "Then we say that $\\lambda$ is an *eigenvalue* of $A$, and $v$ is the corresponding *eigenvector*.\n",
"\n",
"Thus, an eigenvector of $A$ is a nonzero vector $v$ such that when the map $A$ is\n",
"applied, $v$ is merely scaled.\n",
@@ -913,7 +905,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "b4848301",
+ "id": "3121fb59",
"metadata": {
"tags": [
"output_scroll"
@@ -935,7 +927,7 @@
" ax.spines[spine].set_position('zero')\n",
"for spine in ['right', 'top']:\n",
" ax.spines[spine].set_color('none')\n",
- "#ax.grid(alpha=0.4)\n",
+ "# ax.grid(alpha=0.4)\n",
"\n",
"xmin, xmax = -3, 3\n",
"ymin, ymax = -3, 3\n",
@@ -969,7 +961,7 @@
},
{
"cell_type": "markdown",
- "id": "a3d9234f",
+ "id": "d7ca6652",
"metadata": {
"user_expressions": []
},
@@ -978,7 +970,7 @@
"\n",
"So far our definition of eigenvalues and eigenvectors seems straightforward.\n",
"\n",
- "There is, however, one complication we haven't mentioned yet:\n",
+ "There is one complication we haven't mentioned yet:\n",
"\n",
"When solving $Av = \\lambda v$, \n",
"\n",
@@ -987,7 +979,6 @@
"\n",
"We will see some examples below.\n",
"\n",
- "\n",
"### Some mathematical details\n",
"\n",
"We note some mathematical details for more advanced readers.\n",
@@ -998,7 +989,7 @@
"\n",
"This equation has a nonzero solution $v$ only when the columns of $A - \\lambda I$ are linearly dependent.\n",
"\n",
- "This in turn is equivalent to stating that the determinant is zero.\n",
+ "This in turn is equivalent to stating the determinant is zero.\n",
"\n",
"Hence, to find all eigenvalues, we can look for $\\lambda$ such that the\n",
"determinant of $A - \\lambda I$ is zero.\n",
@@ -1009,18 +1000,16 @@
"This in turn implies the existence of $n$ solutions in the complex\n",
"plane, although some might be repeated.\n",
"\n",
- "\n",
- "\n",
"### Facts \n",
"\n",
"Some nice facts about the eigenvalues of a square matrix $A$ are as follows:\n",
"\n",
- "1. The determinant of $A$ equals the product of the eigenvalues.\n",
- "1. The trace of $A$ (the sum of the elements on the principal diagonal) equals the sum of the eigenvalues.\n",
- "1. If $A$ is symmetric, then all of its eigenvalues are real.\n",
- "1. If $A$ is invertible and $\\lambda_1, \\ldots, \\lambda_n$ are its eigenvalues, then the eigenvalues of $A^{-1}$ are $1/\\lambda_1, \\ldots, 1/\\lambda_n$.\n",
+ "1. the determinant of $A$ equals the product of the eigenvalues\n",
+ "2. the trace of $A$ (the sum of the elements on the principal diagonal) equals the sum of the eigenvalues\n",
+ "3. if $A$ is symmetric, then all of its eigenvalues are real\n",
+ "4. if $A$ is invertible and $\\lambda_1, \\ldots, \\lambda_n$ are its eigenvalues, then the eigenvalues of $A^{-1}$ are $1/\\lambda_1, \\ldots, 1/\\lambda_n$.\n",
"\n",
- "A corollary of the first statement is that a matrix is invertible if and only if all its eigenvalues are nonzero.\n",
+ "A corollary of the last statement is that a matrix is invertible if and only if all its eigenvalues are nonzero.\n",
"\n",
"### Computation\n",
"\n",
@@ -1030,7 +1019,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "06cbbfa3",
+ "id": "460d0227",
"metadata": {},
"outputs": [],
"source": [
@@ -1041,22 +1030,22 @@
"\n",
"A = np.array(A)\n",
"evals, evecs = eig(A)\n",
- "evals #eigenvalues"
+ "evals # eigenvalues"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "4fc232f8",
+ "id": "66d0c66e",
"metadata": {},
"outputs": [],
"source": [
- "evecs #eigenvectors"
+ "evecs # eigenvectors"
]
},
{
"cell_type": "markdown",
- "id": "4dfdceac",
+ "id": "1fb3bb32",
"metadata": {
"user_expressions": []
},
@@ -1064,19 +1053,179 @@
"Note that the *columns* of `evecs` are the eigenvectors.\n",
"\n",
"Since any scalar multiple of an eigenvector is an eigenvector with the same\n",
- "eigenvalue (check it), the eig routine normalizes the length of each eigenvector\n",
+ "eigenvalue (which can be verified), the `eig` routine normalizes the length of each eigenvector\n",
"to one.\n",
"\n",
"The eigenvectors and eigenvalues of a map $A$ determine how a vector $v$ is transformed when we repeatedly multiply by $A$.\n",
"\n",
"This is discussed further later.\n",
"\n",
+ "\n",
+ "(la_neumann)=\n",
+ "## The Neumann Series Lemma\n",
+ "\n",
+ "```{index} single: Neumann's Lemma\n",
+ "```\n",
+ "\n",
+ "In this section we present a famous result about series of matrices that has\n",
+ "many applications in economics.\n",
+ "\n",
+ "### Scalar series\n",
+ "\n",
+ "Here's a fundamental result about series:\n",
+ "\n",
+ "If $a$ is a number and $|a| < 1$, then\n",
+ "\n",
+ "```{math}\n",
+ ":label: gp_sum\n",
+ "\n",
+ " \\sum_{k=0}^{\\infty} a^k =\\frac{1}{1-a} = (1 - a)^{-1}\n",
+ "\n",
+ "```\n",
+ "\n",
+ "For a one-dimensional linear equation $x = ax + b$ where x is unknown we can thus conclude that the solution $x^{*}$ is given by:\n",
+ "\n",
+ "$$\n",
+ " x^{*} = \\frac{b}{1-a} = \\sum_{k=0}^{\\infty} a^k b\n",
+ "$$\n",
+ "\n",
+ "### Matrix series\n",
+ "\n",
+ "A generalization of this idea exists in the matrix setting.\n",
+ "\n",
+ "Consider the system of equations $x = Ax + b$ where $A$ is an $n \\times n$\n",
+ "square matrix and $x$ and $b$ are both column vectors in $\\mathbb{R}^n$.\n",
+ "\n",
+ "Using matrix algebra we can conclude that the solution to this system of equations will be given by:\n",
+ "\n",
+ "```{math}\n",
+ ":label: neumann_eqn\n",
+ "\n",
+ " x^{*} = (I-A)^{-1}b\n",
+ "\n",
+ "```\n",
+ "\n",
+ "What guarantees the existence of a unique vector $x^{*}$ that satisfies\n",
+ "{eq}`neumann_eqn`?\n",
+ "\n",
+ "The following is a fundamental result in functional analysis that generalizes\n",
+ "{eq}`gp_sum` to a multivariate case.\n",
+ "\n",
+ "(neumann_series_lemma)=\n",
+ "```{prf:Theorem} Neumann Series Lemma\n",
+ ":label: neumann_series_lemma\n",
+ "\n",
+ "Let $A$ be a square matrix and let $A^k$ be the $k$-th power of $A$.\n",
+ "\n",
+ "Let $r(A)$ be the **spectral radius** of $A$, defined as $\\max_i |\\lambda_i|$, where\n",
+ "\n",
+ "* $\\{\\lambda_i\\}_i$ is the set of eigenvalues of $A$ and\n",
+ "* $|\\lambda_i|$ is the modulus of the complex number $\\lambda_i$\n",
+ "\n",
+ "Neumann's Theorem states the following: If $r(A) < 1$, then $I - A$ is invertible, and\n",
+ "\n",
+ "$$\n",
+ "(I - A)^{-1} = \\sum_{k=0}^{\\infty} A^k\n",
+ "$$\n",
+ "```\n",
+ "\n",
+ "We can see the Neumann Series Lemma in action in the following example."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ea8cd4b6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "A = np.array([[0.4, 0.1],\n",
+ " [0.7, 0.2]])\n",
+ "\n",
+ "evals, evecs = eig(A) # finding eigenvalues and eigenvectors\n",
+ "\n",
+ "r = max(abs(λ) for λ in evals) # compute spectral radius\n",
+ "print(r)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3bd12c26",
+ "metadata": {},
+ "source": [
+ "The spectral radius $r(A)$ obtained is less than 1.\n",
+ "\n",
+ "Thus, we can apply the Neumann Series Lemma to find $(I-A)^{-1}$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bbcdd0cb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "I = np.identity(2) # 2 x 2 identity matrix\n",
+ "B = I - A"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "793f781e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "B_inverse = np.linalg.inv(B) # direct inverse method"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "89dace47",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "A_sum = np.zeros((2, 2)) # power series sum of A\n",
+ "A_power = I\n",
+ "for i in range(50):\n",
+ " A_sum += A_power\n",
+ " A_power = A_power @ A"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "129d3b89",
+ "metadata": {},
+ "source": [
+ "Let's check equality between the sum and the inverse methods."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7c55b918",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.allclose(A_sum, B_inverse)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "59779409",
+ "metadata": {},
+ "source": [
+ "Although we truncate the infinite sum at $k = 50$, both methods give us the same\n",
+ "result which illustrates the result of the Neumann Series Lemma.\n",
+ "\n",
+ "\n",
"## Exercises\n",
"\n",
"```{exercise}\n",
":label: eig1_ex1\n",
"\n",
- "Power iteration is a method for finding the largest absolute eigenvalue of a diagonalizable matrix.\n",
+ "Power iteration is a method for finding the greatest absolute eigenvalue of a diagonalizable matrix.\n",
"\n",
"The method starts with a random vector $b_0$ and repeatedly applies the matrix $A$ to it\n",
"\n",
@@ -1086,9 +1235,9 @@
"\n",
"A thorough discussion of the method can be found [here](https://pythonnumericalmethods.berkeley.edu/notebooks/chapter15.02-The-Power-Method.html).\n",
"\n",
- "In this exercise, implement the power iteration method and use it to find the largest eigenvalue and its corresponding eigenvector.\n",
+ "In this exercise, first implement the power iteration method and use it to find the greatest absolute eigenvalue and its corresponding eigenvector.\n",
"\n",
- "Visualize the convergence.\n",
+ "Then visualize the convergence.\n",
"```\n",
"\n",
"```{solution-start} eig1_ex1\n",
@@ -1103,7 +1252,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "a67c6ef0",
+ "id": "7d3b19ac",
"metadata": {
"mystnb": {
"figure": {
@@ -1115,8 +1264,8 @@
"outputs": [],
"source": [
"# Define a matrix A\n",
- "A = np.array([[1, 0, 3], \n",
- " [0, 2, 0], \n",
+ "A = np.array([[1, 0, 3],\n",
+ " [0, 2, 0],\n",
" [3, 0, 1]])\n",
"\n",
"num_iters = 20\n",
@@ -1127,7 +1276,7 @@
"# Get the leading eigenvector of matrix A\n",
"eigenvector = np.linalg.eig(A)[1][:, 0]\n",
"\n",
- "norm_ls = []\n",
+ "errors = []\n",
"res = []\n",
"\n",
"# Power iteration loop\n",
@@ -1138,35 +1287,36 @@
" b = b / np.linalg.norm(b)\n",
" # Append b to the list of eigenvector approximations\n",
" res.append(b)\n",
- " norm = np.linalg.norm(np.array(b) \n",
- " - eigenvector)\n",
- " norm_ls.append(norm)\n",
+ " err = np.linalg.norm(np.array(b)\n",
+ " - eigenvector)\n",
+ " errors.append(err)\n",
"\n",
- "dominant_eigenvalue = np.dot(A @ b, b) / np.dot(b, b)\n",
- "print(f'The approximated dominant eigenvalue is {dominant_eigenvalue:.2f}')\n",
+ "greatest_eigenvalue = np.dot(A @ b, b) / np.dot(b, b)\n",
+ "print(f'The approximated greatest absolute eigenvalue is \\\n",
+ " {greatest_eigenvalue:.2f}')\n",
"print('The real eigenvalue is', np.linalg.eig(A)[0])\n",
"\n",
"# Plot the eigenvector approximations for each iteration\n",
"plt.figure(figsize=(10, 6))\n",
"plt.xlabel('iterations')\n",
- "plt.ylabel('Norm')\n",
- "_ = plt.plot(norm_ls)"
+ "plt.ylabel('error')\n",
+ "_ = plt.plot(errors)"
]
},
{
"cell_type": "markdown",
- "id": "743b95f2",
+ "id": "c5a64023",
"metadata": {
"user_expressions": []
},
"source": [
- "Then we can look at the trajectory of the eigenvector approximation"
+ "Then we can look at the trajectory of the eigenvector approximation."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "b6743c4b",
+ "id": "5bd57327",
"metadata": {
"mystnb": {
"figure": {
@@ -1182,35 +1332,34 @@
"ax = fig.add_subplot(111, projection='3d')\n",
"\n",
"# Plot the eigenvectors\n",
- "ax.scatter(eigenvector[0], \n",
- " eigenvector[1], \n",
- " eigenvector[2], \n",
- " color='r', s = 80)\n",
+ "ax.scatter(eigenvector[0],\n",
+ " eigenvector[1],\n",
+ " eigenvector[2],\n",
+ " color='r', s=80)\n",
"\n",
"for i, vec in enumerate(res):\n",
- " ax.scatter(vec[0], vec[1], vec[2], \n",
- " color='b', \n",
- " alpha=(i+1)/(num_iters+1), \n",
- " s = 80)\n",
+ " ax.scatter(vec[0], vec[1], vec[2],\n",
+ " color='b',\n",
+ " alpha=(i+1)/(num_iters+1),\n",
+ " s=80)\n",
"\n",
"ax.set_xlabel('x')\n",
"ax.set_ylabel('y')\n",
"ax.set_zlabel('z')\n",
"ax.tick_params(axis='both', which='major', labelsize=7)\n",
"\n",
- "points = [plt.Line2D([0], [0], linestyle='none', \n",
+ "points = [plt.Line2D([0], [0], linestyle='none',\n",
" c=i, marker='o') for i in ['r', 'b']]\n",
- "ax.legend(points, ['actual eigenvector', \n",
+ "ax.legend(points, ['actual eigenvector',\n",
" r'approximated eigenvector ($b_k$)'])\n",
"ax.set_box_aspect(aspect=None, zoom=0.8)\n",
"\n",
- "# Show the plot\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
- "id": "853ed760",
+ "id": "42e34a0c",
"metadata": {
"user_expressions": []
},
@@ -1237,11 +1386,11 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "b537065d",
+ "id": "9d7e0a99",
"metadata": {},
"outputs": [],
"source": [
- "A = np.array([[1, 2], \n",
+ "A = np.array([[1, 2],\n",
" [1, 1]])\n",
"v = (0.4, -0.4)\n",
"n = 11\n",
@@ -1249,28 +1398,30 @@
"# Compute eigenvectors and eigenvalues\n",
"eigenvalues, eigenvectors = np.linalg.eig(A)\n",
"\n",
- "print(f\"eigenvalues:\\n {eigenvalues}\")\n",
- "print(f\"eigenvectors:\\n {eigenvectors}\")\n",
+ "print(f'eigenvalues:\\n {eigenvalues}')\n",
+ "print(f'eigenvectors:\\n {eigenvectors}')\n",
"\n",
"plot_series(A, v, n)"
]
},
{
"cell_type": "markdown",
- "id": "bb434517",
+ "id": "8fac07a1",
"metadata": {
"user_expressions": []
},
"source": [
"The result seems to converge to the eigenvector of $A$ with the largest eigenvalue.\n",
"\n",
- "Let's use a vector field to visualize the transformation brought by A."
+ "Let's use a [vector field](https://en.wikipedia.org/wiki/Vector_field) to visualize the transformation brought by A.\n",
+ "\n",
+ "(This is a more advanced topic in linear algebra, please step ahead if you are comfortable with the math.)"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "a21574a2",
+ "id": "299137cd",
"metadata": {
"mystnb": {
"figure": {
@@ -1282,32 +1433,33 @@
"outputs": [],
"source": [
"# Create a grid of points\n",
- "x, y = np.meshgrid(np.linspace(-5, 5, 15), \n",
- " np.linspace(-5, 5, 20))\n",
+ "x, y = np.meshgrid(np.linspace(-5, 5, 15),\n",
+ " np.linspace(-5, 5, 20))\n",
"\n",
"# Apply the matrix A to each point in the vector field\n",
"vec_field = np.stack([x, y])\n",
"u, v = np.tensordot(A, vec_field, axes=1)\n",
"\n",
"# Plot the transformed vector field\n",
- "c = plt.streamplot(x, y, u - x, v - y, \n",
- " density=1, linewidth=None, color='#A23BEC')\n",
+ "c = plt.streamplot(x, y, u - x, v - y,\n",
+ " density=1, linewidth=None, color='#A23BEC')\n",
"c.lines.set_alpha(0.5)\n",
"c.arrows.set_alpha(0.5)\n",
"\n",
"# Draw eigenvectors\n",
"origin = np.zeros((2, len(eigenvectors)))\n",
- "parameters = {'color':['b', 'g'], 'angles':'xy', \n",
- " 'scale_units':'xy', 'scale':0.1, 'width':0.01}\n",
- "plt.quiver(*origin, eigenvectors[0], \n",
- " eigenvectors[1], **parameters)\n",
- "plt.quiver(*origin, - eigenvectors[0], \n",
- " - eigenvectors[1], **parameters)\n",
+ "parameters = {'color': ['b', 'g'], 'angles': 'xy',\n",
+ " 'scale_units': 'xy', 'scale': 0.1, 'width': 0.01}\n",
+ "plt.quiver(*origin, eigenvectors[0],\n",
+ " eigenvectors[1], **parameters)\n",
+ "plt.quiver(*origin, - eigenvectors[0],\n",
+ " - eigenvectors[1], **parameters)\n",
"\n",
"colors = ['b', 'g']\n",
"lines = [Line2D([0], [0], color=c, linewidth=3) for c in colors]\n",
"labels = [\"2.4 eigenspace\", \"0.4 eigenspace\"]\n",
- "plt.legend(lines, labels,loc='center left', bbox_to_anchor=(1, 0.5))\n",
+ "plt.legend(lines, labels, loc='center left',\n",
+ " bbox_to_anchor=(1, 0.5))\n",
"\n",
"plt.xlabel(\"x\")\n",
"plt.ylabel(\"y\")\n",
@@ -1318,7 +1470,7 @@
},
{
"cell_type": "markdown",
- "id": "83367402",
+ "id": "f9e3d9bb",
"metadata": {
"user_expressions": []
},
@@ -1354,7 +1506,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "4a9a5d99",
+ "id": "cf30f874",
"metadata": {
"mystnb": {
"figure": {
@@ -1365,7 +1517,7 @@
},
"outputs": [],
"source": [
- "figure, ax = plt.subplots(1,3, figsize = (15, 5))\n",
+ "figure, ax = plt.subplots(1, 3, figsize=(15, 5))\n",
"A = np.array([[sqrt(3) + 1, -2],\n",
" [1, sqrt(3) - 1]])\n",
"A = (1/(2*sqrt(2))) * A\n",
@@ -1393,30 +1545,30 @@
" eigenvectors_real = eigenvectors.real\n",
"\n",
" # Create a grid of points\n",
- " x, y = np.meshgrid(np.linspace(-20, 20, 15), \n",
- " np.linspace(-20, 20, 20))\n",
+ " x, y = np.meshgrid(np.linspace(-20, 20, 15),\n",
+ " np.linspace(-20, 20, 20))\n",
"\n",
" # Apply the matrix A to each point in the vector field\n",
" vec_field = np.stack([x, y])\n",
" u, v = np.tensordot(M, vec_field, axes=1)\n",
"\n",
" # Plot the transformed vector field\n",
- " c = ax[i].streamplot(x, y, u - x, v - y,\n",
- " density=1, linewidth=None, color='#A23BEC')\n",
+ " c = ax[i].streamplot(x, y, u - x, v - y, density=1,\n",
+ " linewidth=None, color='#A23BEC')\n",
" c.lines.set_alpha(0.5)\n",
" c.arrows.set_alpha(0.5)\n",
- " \n",
+ "\n",
" # Draw eigenvectors\n",
- " parameters = {'color':['b', 'g'], 'angles':'xy', \n",
- " 'scale_units':'xy', 'scale':1, \n",
- " 'width':0.01, 'alpha':0.5}\n",
+ " parameters = {'color': ['b', 'g'], 'angles': 'xy',\n",
+ " 'scale_units': 'xy', 'scale': 1,\n",
+ " 'width': 0.01, 'alpha': 0.5}\n",
" origin = np.zeros((2, len(eigenvectors)))\n",
- " ax[i].quiver(*origin, eigenvectors_real[0], \n",
- " eigenvectors_real[1], **parameters)\n",
- " ax[i].quiver(*origin, \n",
- " - eigenvectors_real[0], \n",
- " - eigenvectors_real[1], \n",
- " **parameters)\n",
+ " ax[i].quiver(*origin, eigenvectors_real[0],\n",
+ " eigenvectors_real[1], **parameters)\n",
+ " ax[i].quiver(*origin,\n",
+ " - eigenvectors_real[0],\n",
+ " - eigenvectors_real[1],\n",
+ " **parameters)\n",
"\n",
" ax[i].set_xlabel(\"x-axis\")\n",
" ax[i].set_ylabel(\"y-axis\")\n",
@@ -1428,7 +1580,7 @@
},
{
"cell_type": "markdown",
- "id": "8ca7f153",
+ "id": "f5873491",
"metadata": {
"user_expressions": []
},
@@ -1437,13 +1589,13 @@
"\n",
"The pattern demonstrated here is because we have complex eigenvalues and eigenvectors.\n",
"\n",
- "We can plot the complex plane for one of the matrices using `Arrow3D` class retrieved from [stackoverflow](https://stackoverflow.com/questions/22867620/putting-arrowheads-on-vectors-in-matplotlibs-3d-plot)."
+ "We can plot the complex plane for one of the matrices using `Arrow3D` class retrieved from [stackoverflow](https://stackoverflow.com/questions/22867620/putting-arrowheads-on-vectors-in-a-3d-plot)."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "2063cbf6",
+ "id": "be19e81c",
"metadata": {
"mystnb": {
"figure": {
@@ -1456,20 +1608,23 @@
"source": [
"class Arrow3D(FancyArrowPatch):\n",
" def __init__(self, xs, ys, zs, *args, **kwargs):\n",
- " super().__init__((0,0), (0,0), *args, **kwargs)\n",
+ " super().__init__((0, 0), (0, 0), *args, **kwargs)\n",
" self._verts3d = xs, ys, zs\n",
"\n",
- " def do_3d_projection(self, renderer=None):\n",
+ " def do_3d_projection(self):\n",
" xs3d, ys3d, zs3d = self._verts3d\n",
- " xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M)\n",
- " self.set_positions((0.1*xs[0],0.1*ys[0]),(0.1*xs[1],0.1*ys[1]))\n",
+ " xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d,\n",
+ " self.axes.M)\n",
+ " self.set_positions((0.1*xs[0], 0.1*ys[0]),\n",
+ " (0.1*xs[1], 0.1*ys[1]))\n",
"\n",
" return np.min(zs)\n",
"\n",
+ "\n",
"eigenvalues, eigenvectors = np.linalg.eig(A)\n",
"\n",
"# Create meshgrid for vector field\n",
- "x, y = np.meshgrid(np.linspace(-2, 2, 15), \n",
+ "x, y = np.meshgrid(np.linspace(-2, 2, 15),\n",
" np.linspace(-2, 2, 15))\n",
"\n",
"# Calculate vector field (real and imaginary parts)\n",
@@ -1482,18 +1637,18 @@
"fig = plt.figure()\n",
"ax = fig.add_subplot(111, projection='3d')\n",
"vlength = np.linalg.norm(eigenvectors)\n",
- "ax.quiver(x, y, u_imag, u_real-x, v_real-y, v_imag-u_imag, \n",
- " colors = 'b', alpha=0.3, length = .2, \n",
- " arrow_length_ratio = 0.01)\n",
+ "ax.quiver(x, y, u_imag, u_real-x, v_real-y, v_imag-u_imag,\n",
+ " colors='b', alpha=0.3, length=.2,\n",
+ " arrow_length_ratio=0.01)\n",
"\n",
- "arrow_prop_dict = dict(mutation_scale=5, \n",
- " arrowstyle='-|>', shrinkA=0, shrinkB=0)\n",
+ "arrow_prop_dict = dict(mutation_scale=5,\n",
+ " arrowstyle='-|>', shrinkA=0, shrinkB=0)\n",
"\n",
"# Plot 3D eigenvectors\n",
"for c, i in zip(['b', 'g'], [0, 1]):\n",
- " a = Arrow3D([0, eigenvectors[0][i].real], \n",
- " [0, eigenvectors[1][i].real], \n",
- " [0, eigenvectors[1][i].imag], \n",
+ " a = Arrow3D([0, eigenvectors[0][i].real],\n",
+ " [0, eigenvectors[1][i].real],\n",
+ " [0, eigenvectors[1][i].imag],\n",
" color=c, **arrow_prop_dict)\n",
" ax.add_artist(a)\n",
"\n",
@@ -1509,7 +1664,7 @@
},
{
"cell_type": "markdown",
- "id": "fc6d09ac",
+ "id": "6ea65314",
"metadata": {
"user_expressions": []
},
@@ -1520,12 +1675,77 @@
}
],
"metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.14.5"
+ }
+ },
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
- }
+ },
+ "source_map": [
+ 14,
+ 41,
+ 48,
+ 124,
+ 129,
+ 169,
+ 194,
+ 285,
+ 303,
+ 310,
+ 326,
+ 333,
+ 349,
+ 356,
+ 370,
+ 375,
+ 519,
+ 558,
+ 565,
+ 569,
+ 573,
+ 577,
+ 581,
+ 604,
+ 649,
+ 659,
+ 665,
+ 675,
+ 682,
+ 692,
+ 732,
+ 781,
+ 832,
+ 843,
+ 847,
+ 930,
+ 938,
+ 944,
+ 949,
+ 953,
+ 959,
+ 963,
+ 965,
+ 999,
+ 1046,
+ 1050,
+ 1087,
+ 1107,
+ 1122,
+ 1130,
+ 1173,
+ 1202,
+ 1270,
+ 1278,
+ 1341
+ ]
},
"nbformat": 4,
"nbformat_minor": 5
-}
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/eigen_I.md b/book/_build/html/_sources/eigen_I.md
new file mode 100644
index 0000000..948b2f0
--- /dev/null
+++ b/book/_build/html/_sources/eigen_I.md
@@ -0,0 +1,1344 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.14.5
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
++++ {"user_expressions": []}
+
+(eigen)=
+# Eigenvalues and Eigenvectors
+
+```{index} single: Eigenvalues and Eigenvectors
+```
+
+## Overview
+
+Eigenvalues and eigenvectors are a relatively advanced topic in linear algebra.
+
+At the same time, these concepts are extremely useful for
+
+* economic modeling (especially dynamics!)
+* statistics
+* some parts of applied mathematics
+* machine learning
+* and many other fields of science.
+
+In this lecture we explain the basics of eigenvalues and eigenvectors and introduce the Neumann Series Lemma.
+
+We assume in this lecture that students are familiar with matrices
+ and understand {doc}`the basics of matrix algebra`.
+
+We will use the following imports:
+
+```{code-cell} ipython3
+import matplotlib.pyplot as plt
+import numpy as np
+from numpy.linalg import matrix_power
+from matplotlib.lines import Line2D
+from matplotlib.patches import FancyArrowPatch
+from mpl_toolkits.mplot3d import proj3d
+```
+
+(matrices_as_transformation)=
+## Matrices as transformations
+
+Let's start by discussing an important concept concerning matrices.
+
+### Mapping vectors to vectors
+
+One way to think about a matrix is as a rectangular collection of
+numbers.
+
+Another way to think about a matrix is as a *map* (i.e., as a function) that
+transforms vectors to new vectors.
+
+To understand the second point of view, suppose we multiply an $n \times m$
+matrix $A$ with an $m \times 1$ column vector $x$ to obtain an $n \times 1$
+column vector $y$:
+
+$$
+ Ax = y
+$$
+
+If we fix $A$ and consider different choices of $x$, we can understand $A$ as
+a map transforming $x$ to $Ax$.
+
+Because $A$ is $n \times m$, it transforms $m$-vectors to $n$-vectors.
+
+We can write this formally as $A \colon \mathbb{R}^m \rightarrow \mathbb{R}^n$.
+
+You might argue that if $A$ is a function then we should write
+$A(x) = y$ rather than $Ax = y$ but the second notation is more conventional.
+
+### Square matrices
+
+Let's restrict our discussion to square matrices.
+
+In the above discussion, this means that $m=n$ and $A$ maps $\mathbb R^n$ to
+itself.
+
+This means $A$ is an $n \times n$ matrix that maps (or "transforms") a vector
+$x$ in $\mathbb{R}^n$ to a new vector $y=Ax$ also in $\mathbb{R}^n$.
+
+```{prf:example}
+:label: eigen1_ex_sq
+
+$$
+ \begin{bmatrix}
+ 2 & 1 \\
+ -1 & 1
+ \end{bmatrix}
+ \begin{bmatrix}
+ 1 \\
+ 3
+ \end{bmatrix}
+ =
+ \begin{bmatrix}
+ 5 \\
+ 2
+ \end{bmatrix}
+$$
+
+Here, the matrix
+
+$$
+ A = \begin{bmatrix} 2 & 1 \\
+ -1 & 1
+ \end{bmatrix}
+$$
+
+transforms the vector $x = \begin{bmatrix} 1 \\ 3 \end{bmatrix}$ to the vector
+$y = \begin{bmatrix} 5 \\ 2 \end{bmatrix}$.
+```
+
+Let's visualize this using Python:
+
+```{code-cell} ipython3
+A = np.array([[2, 1],
+ [-1, 1]])
+```
+
+```{code-cell} ipython3
+from math import sqrt
+
+fig, ax = plt.subplots()
+# Set the axes through the origin
+
+for spine in ['left', 'bottom']:
+ ax.spines[spine].set_position('zero')
+for spine in ['right', 'top']:
+ ax.spines[spine].set_color('none')
+
+ax.set(xlim=(-2, 6), ylim=(-2, 4), aspect=1)
+
+vecs = ((1, 3), (5, 2))
+c = ['r', 'black']
+for i, v in enumerate(vecs):
+ ax.annotate('', xy=v, xytext=(0, 0),
+ arrowprops=dict(color=c[i],
+ shrink=0,
+ alpha=0.7,
+ width=0.5))
+
+ax.text(0.2 + 1, 0.2 + 3, 'x=$(1,3)$')
+ax.text(0.2 + 5, 0.2 + 2, 'Ax=$(5,2)$')
+
+ax.annotate('', xy=(sqrt(10/29) * 5, sqrt(10/29) * 2), xytext=(0, 0),
+ arrowprops=dict(color='purple',
+ shrink=0,
+ alpha=0.7,
+ width=0.5))
+
+ax.annotate('', xy=(1, 2/5), xytext=(1/3, 1),
+ arrowprops={'arrowstyle': '->',
+ 'connectionstyle': 'arc3,rad=-0.3'},
+ horizontalalignment='center')
+ax.text(0.8, 0.8, f'θ', fontsize=14)
+
+plt.show()
+```
+
++++ {"user_expressions": []}
+
+One way to understand this transformation is that $A$
+
+* first rotates $x$ by some angle $\theta$ and
+* then scales it by some scalar $\gamma$ to obtain the image $y$ of $x$.
+
+
+
+## Types of transformations
+
+Let's examine some standard transformations we can perform with matrices.
+
+Below we visualize transformations by thinking of vectors as points
+instead of arrows.
+
+We consider how a given matrix transforms
+
+* a grid of points and
+* a set of points located on the unit circle in $\mathbb{R}^2$.
+
+To build the transformations we will use two functions, called `grid_transform` and `circle_transform`.
+
+Each of these functions visualizes the actions of a given $2 \times 2$ matrix $A$.
+
+```{code-cell} ipython3
+:tags: [hide-input]
+
+def colorizer(x, y):
+ r = min(1, 1-y/3)
+ g = min(1, 1+y/3)
+ b = 1/4 + x/16
+ return (r, g, b)
+
+
+def grid_transform(A=np.array([[1, -1], [1, 1]])):
+ xvals = np.linspace(-4, 4, 9)
+ yvals = np.linspace(-3, 3, 7)
+ xygrid = np.column_stack([[x, y] for x in xvals for y in yvals])
+ uvgrid = A @ xygrid
+
+ colors = list(map(colorizer, xygrid[0], xygrid[1]))
+
+ fig, ax = plt.subplots(1, 2, figsize=(10, 5))
+
+ for axes in ax:
+ axes.set(xlim=(-11, 11), ylim=(-11, 11))
+ axes.set_xticks([])
+ axes.set_yticks([])
+ for spine in ['left', 'bottom']:
+ axes.spines[spine].set_position('zero')
+ for spine in ['right', 'top']:
+ axes.spines[spine].set_color('none')
+
+ # Plot x-y grid points
+ ax[0].scatter(xygrid[0], xygrid[1], s=36, c=colors, edgecolor="none")
+ # ax[0].grid(True)
+ # ax[0].axis("equal")
+ ax[0].set_title("points $x_1, x_2, \cdots, x_k$")
+
+ # Plot transformed grid points
+ ax[1].scatter(uvgrid[0], uvgrid[1], s=36, c=colors, edgecolor="none")
+ # ax[1].grid(True)
+ # ax[1].axis("equal")
+ ax[1].set_title("points $Ax_1, Ax_2, \cdots, Ax_k$")
+
+ plt.show()
+
+
+def circle_transform(A=np.array([[-1, 2], [0, 1]])):
+
+ fig, ax = plt.subplots(1, 2, figsize=(10, 5))
+
+ for axes in ax:
+ axes.set(xlim=(-4, 4), ylim=(-4, 4))
+ axes.set_xticks([])
+ axes.set_yticks([])
+ for spine in ['left', 'bottom']:
+ axes.spines[spine].set_position('zero')
+ for spine in ['right', 'top']:
+ axes.spines[spine].set_color('none')
+
+ θ = np.linspace(0, 2 * np.pi, 150)
+ r = 1
+
+ θ_1 = np.empty(12)
+ for i in range(12):
+ θ_1[i] = 2 * np.pi * (i/12)
+
+ x = r * np.cos(θ)
+ y = r * np.sin(θ)
+ a = r * np.cos(θ_1)
+ b = r * np.sin(θ_1)
+ a_1 = a.reshape(1, -1)
+ b_1 = b.reshape(1, -1)
+ colors = list(map(colorizer, a, b))
+ ax[0].plot(x, y, color='black', zorder=1)
+ ax[0].scatter(a_1, b_1, c=colors, alpha=1, s=60,
+ edgecolors='black', zorder=2)
+ ax[0].set_title("unit circle in $\mathbb{R}^2$")
+
+ x1 = x.reshape(1, -1)
+ y1 = y.reshape(1, -1)
+ ab = np.concatenate((a_1, b_1), axis=0)
+ transformed_ab = A @ ab
+ transformed_circle_input = np.concatenate((x1, y1), axis=0)
+ transformed_circle = A @ transformed_circle_input
+ ax[1].plot(transformed_circle[0, :],
+ transformed_circle[1, :], color='black', zorder=1)
+ ax[1].scatter(transformed_ab[0, :], transformed_ab[1:,],
+ color=colors, alpha=1, s=60, edgecolors='black', zorder=2)
+ ax[1].set_title("transformed circle")
+
+ plt.show()
+```
+
++++ {"user_expressions": []}
+
+### Scaling
+
+A matrix of the form
+
+$$
+ \begin{bmatrix}
+ \alpha & 0
+ \\ 0 & \beta
+ \end{bmatrix}
+$$
+
+scales vectors across the x-axis by a factor $\alpha$ and along the y-axis by
+a factor $\beta$.
+
+Here we illustrate a simple example where $\alpha = \beta = 3$.
+
+```{code-cell} ipython3
+A = np.array([[3, 0], # scaling by 3 in both directions
+ [0, 3]])
+grid_transform(A)
+circle_transform(A)
+```
+
++++ {"user_expressions": []}
+
+### Shearing
+
+A "shear" matrix of the form
+
+$$
+ \begin{bmatrix}
+ 1 & \lambda \\
+ 0 & 1
+ \end{bmatrix}
+$$
+
+stretches vectors along the x-axis by an amount proportional to the
+y-coordinate of a point.
+
+```{code-cell} ipython3
+A = np.array([[1, 2], # shear along x-axis
+ [0, 1]])
+grid_transform(A)
+circle_transform(A)
+```
+
++++ {"user_expressions": []}
+
+### Rotation
+
+A matrix of the form
+
+$$
+ \begin{bmatrix}
+ \cos \theta & \sin \theta
+ \\ - \sin \theta & \cos \theta
+ \end{bmatrix}
+$$
+is called a _rotation matrix_.
+
+This matrix rotates vectors clockwise by an angle $\theta$.
+
+```{code-cell} ipython3
+θ = np.pi/4 # 45 degree clockwise rotation
+A = np.array([[np.cos(θ), np.sin(θ)],
+ [-np.sin(θ), np.cos(θ)]])
+grid_transform(A)
+```
+
++++ {"user_expressions": []}
+
+### Permutation
+
+The permutation matrix
+
+$$
+ \begin{bmatrix}
+ 0 & 1 \\
+ 1 & 0
+ \end{bmatrix}
+$$
+interchanges the coordinates of a vector.
+
+```{code-cell} ipython3
+A = np.column_stack([[0, 1], [1, 0]])
+grid_transform(A)
+```
+
++++ {"user_expressions": []}
+
+More examples of common transition matrices can be found [here](https://en.wikipedia.org/wiki/Transformation_matrix#Examples_in_2_dimensions).
+
+## Matrix multiplication as composition
+
+Since matrices act as functions that transform one vector to another, we can
+apply the concept of function composition to matrices as well.
+
+
+### Linear compositions
+
+Consider the two matrices
+
+$$
+ A =
+ \begin{bmatrix}
+ 0 & 1 \\
+ -1 & 0
+ \end{bmatrix}
+ \quad \text{and} \quad
+ B =
+ \begin{bmatrix}
+ 1 & 2 \\
+ 0 & 1
+ \end{bmatrix}
+$$
+
+What will the output be when we try to obtain $ABx$ for some $2 \times 1$
+vector $x$?
+
+$$
+\color{red}{\underbrace{
+ \color{black}{\begin{bmatrix}
+ 0 & 1 \\
+ -1 & 0
+ \end{bmatrix}}
+}_{\textstyle A} }
+\color{red}{\underbrace{
+ \color{black}{\begin{bmatrix}
+ 1 & 2 \\
+ 0 & 1
+ \end{bmatrix}}
+}_{\textstyle B}}
+\color{red}{\overbrace{
+ \color{black}{\begin{bmatrix}
+ 1 \\
+ 3
+ \end{bmatrix}}
+}^{\textstyle x}}
+\rightarrow
+\color{red}{\underbrace{
+ \color{black}{\begin{bmatrix}
+ 0 & 1 \\
+ -1 & -2
+ \end{bmatrix}}
+}_{\textstyle AB}}
+\color{red}{\overbrace{
+ \color{black}{\begin{bmatrix}
+ 1 \\
+ 3
+ \end{bmatrix}}
+}^{\textstyle x}}
+\rightarrow
+\color{red}{\overbrace{
+ \color{black}{\begin{bmatrix}
+ 3 \\
+ -7
+ \end{bmatrix}}
+}^{\textstyle y}}
+$$
+
+$$
+\color{red}{\underbrace{
+ \color{black}{\begin{bmatrix}
+ 0 & 1 \\
+ -1 & 0
+ \end{bmatrix}}
+}_{\textstyle A} }
+\color{red}{\underbrace{
+ \color{black}{\begin{bmatrix}
+ 1 & 2 \\
+ 0 & 1
+ \end{bmatrix}}
+}_{\textstyle B}}
+\color{red}{\overbrace{
+ \color{black}{\begin{bmatrix}
+ 1 \\
+ 3
+ \end{bmatrix}}
+}^{\textstyle x}}
+\rightarrow
+\color{red}{\underbrace{
+ \color{black}{\begin{bmatrix}
+ 0 & 1 \\
+ -1 & 0
+ \end{bmatrix}}
+}_{\textstyle A}}
+\color{red}{\overbrace{
+ \color{black}{\begin{bmatrix}
+ 7 \\
+ 3
+ \end{bmatrix}}
+}^{\textstyle Bx}}
+\rightarrow
+\color{red}{\overbrace{
+ \color{black}{\begin{bmatrix}
+ 3 \\
+ -7
+ \end{bmatrix}}
+}^{\textstyle y}}
+$$
+
+We can observe that applying the transformation $AB$ on the vector $x$ is the
+same as first applying $B$ on $x$ and then applying $A$ on the vector $Bx$.
+
+Thus the matrix product $AB$ is the
+[composition](https://en.wikipedia.org/wiki/Function_composition) of the
+matrix transformations $A$ and $B$
+
+This means first apply transformation $B$ and then
+transformation $A$.
+
+When we matrix multiply an $n \times m$ matrix $A$ with an $m \times k$ matrix
+$B$ the obtained matrix product is an $n \times k$ matrix $AB$.
+
+Thus, if $A$ and $B$ are transformations such that $A \colon \mathbb{R}^m \to
+\mathbb{R}^n$ and $B \colon \mathbb{R}^k \to \mathbb{R}^m$, then $AB$
+transforms $\mathbb{R}^k$ to $\mathbb{R}^n$.
+
+Viewing matrix multiplication as composition of maps helps us
+understand why, under matrix multiplication, $AB$ is generally not equal to $BA$.
+
+(After all, when we compose functions, the order usually matters.)
+
+### Examples
+
+Let $A$ be the $90^{\circ}$ clockwise rotation matrix given by
+$\begin{bmatrix} 0 & 1 \\ -1 & 0 \end{bmatrix}$ and let $B$ be a shear matrix
+along the x-axis given by $\begin{bmatrix} 1 & 2 \\ 0 & 1 \end{bmatrix}$.
+
+We will visualize how a grid of points changes when we apply the
+transformation $AB$ and then compare it with the transformation $BA$.
+
+```{code-cell} ipython3
+:tags: [hide-input]
+
+def grid_composition_transform(A=np.array([[1, -1], [1, 1]]),
+ B=np.array([[1, -1], [1, 1]])):
+ xvals = np.linspace(-4, 4, 9)
+ yvals = np.linspace(-3, 3, 7)
+ xygrid = np.column_stack([[x, y] for x in xvals for y in yvals])
+ uvgrid = B @ xygrid
+ abgrid = A @ uvgrid
+
+ colors = list(map(colorizer, xygrid[0], xygrid[1]))
+
+ fig, ax = plt.subplots(1, 3, figsize=(15, 5))
+
+ for axes in ax:
+ axes.set(xlim=(-12, 12), ylim=(-12, 12))
+ axes.set_xticks([])
+ axes.set_yticks([])
+ for spine in ['left', 'bottom']:
+ axes.spines[spine].set_position('zero')
+ for spine in ['right', 'top']:
+ axes.spines[spine].set_color('none')
+
+ # Plot grid points
+ ax[0].scatter(xygrid[0], xygrid[1], s=36, c=colors, edgecolor="none")
+ ax[0].set_title("points $x_1, x_2, \cdots, x_k$")
+
+ # Plot intermediate grid points
+ ax[1].scatter(uvgrid[0], uvgrid[1], s=36, c=colors, edgecolor="none")
+ ax[1].set_title("points $Bx_1, Bx_2, \cdots, Bx_k$")
+
+ # Plot transformed grid points
+ ax[2].scatter(abgrid[0], abgrid[1], s=36, c=colors, edgecolor="none")
+ ax[2].set_title("points $ABx_1, ABx_2, \cdots, ABx_k$")
+
+ plt.show()
+```
+
+```{code-cell} ipython3
+A = np.array([[0, 1], # 90 degree clockwise rotation
+ [-1, 0]])
+B = np.array([[1, 2], # shear along x-axis
+ [0, 1]])
+```
+
++++ {"user_expressions": []}
+
+#### Shear then rotate
+
+```{code-cell} ipython3
+grid_composition_transform(A, B) # transformation AB
+```
+
++++ {"user_expressions": []}
+
+#### Rotate then shear
+
+```{code-cell} ipython3
+grid_composition_transform(B,A) # transformation BA
+```
+
++++ {"user_expressions": []}
+
+It is evident that the transformation $AB$ is not the same as the transformation $BA$.
+
+## Iterating on a fixed map
+
+In economics (and especially in dynamic modeling), we are often interested in
+analyzing behavior where we repeatedly apply a fixed matrix.
+
+For example, given a vector $v$ and a matrix $A$, we are interested in
+studying the sequence
+
+$$
+ v, \quad
+ Av, \quad
+ AAv = A^2v, \quad \ldots
+$$
+
+Let's first see examples of a sequence of iterates $(A^k v)_{k \geq 0}$ under
+different maps $A$.
+
+(plot_series)=
+
+```{code-cell} ipython3
+def plot_series(A, v, n):
+
+ B = np.array([[1, -1],
+ [1, 0]])
+
+ fig, ax = plt.subplots()
+
+ ax.set(xlim=(-4, 4), ylim=(-4, 4))
+ ax.set_xticks([])
+ ax.set_yticks([])
+ for spine in ['left', 'bottom']:
+ ax.spines[spine].set_position('zero')
+ for spine in ['right', 'top']:
+ ax.spines[spine].set_color('none')
+
+ θ = np.linspace(0, 2 * np.pi, 150)
+ r = 2.5
+ x = r * np.cos(θ)
+ y = r * np.sin(θ)
+ x1 = x.reshape(1, -1)
+ y1 = y.reshape(1, -1)
+ xy = np.concatenate((x1, y1), axis=0)
+
+ ellipse = B @ xy
+ ax.plot(ellipse[0, :], ellipse[1, :], color='black',
+ linestyle=(0, (5, 10)), linewidth=0.5)
+
+ # Initialize holder for trajectories
+ colors = plt.cm.rainbow(np.linspace(0, 1, 20))
+
+ for i in range(n):
+ iteration = matrix_power(A, i) @ v
+ v1 = iteration[0]
+ v2 = iteration[1]
+ ax.scatter(v1, v2, color=colors[i])
+ if i == 0:
+ ax.text(v1+0.25, v2, f'$v$')
+ elif i == 1:
+ ax.text(v1+0.25, v2, f'$Av$')
+ elif 1 < i < 4:
+ ax.text(v1+0.25, v2, f'$A^{i}v$')
+ plt.show()
+```
+
+```{code-cell} ipython3
+A = np.array([[sqrt(3) + 1, -2],
+ [1, sqrt(3) - 1]])
+A = (1/(2*sqrt(2))) * A
+v = (-3, -3)
+n = 12
+
+plot_series(A, v, n)
+```
+
++++ {"user_expressions": []}
+
+Here with each iteration the vectors get shorter, i.e., move closer to the origin.
+
+In this case, repeatedly multiplying a vector by $A$ makes the vector "spiral in".
+
+```{code-cell} ipython3
+B = np.array([[sqrt(3) + 1, -2],
+ [1, sqrt(3) - 1]])
+B = (1/2) * B
+v = (2.5, 0)
+n = 12
+
+plot_series(B, v, n)
+```
+
++++ {"user_expressions": []}
+
+Here with each iteration vectors do not tend to get longer or shorter.
+
+In this case, repeatedly multiplying a vector by $A$ simply "rotates it around
+an ellipse".
+
+```{code-cell} ipython3
+B = np.array([[sqrt(3) + 1, -2],
+ [1, sqrt(3) - 1]])
+B = (1/sqrt(2)) * B
+v = (-1, -0.25)
+n = 6
+
+plot_series(B, v, n)
+```
+
++++ {"user_expressions": []}
+
+Here with each iteration vectors tend to get longer, i.e., farther from the
+origin.
+
+In this case, repeatedly multiplying a vector by $A$ makes the vector "spiral out".
+
+We thus observe that the sequence $(A^kv)_{k \geq 0}$ behaves differently depending on the map $A$ itself.
+
+We now discuss the property of A that determines this behavior.
+
+(la_eigenvalues)=
+## Eigenvalues
+
+```{index} single: Linear Algebra; Eigenvalues
+```
+
+In this section we introduce the notions of eigenvalues and eigenvectors.
+
+### Definitions
+
+Let $A$ be an $n \times n$ square matrix.
+
+If $\lambda$ is scalar and $v$ is a non-zero $n$-vector such that
+
+$$
+A v = \lambda v.
+$$
+
+
+Then we say that $\lambda$ is an *eigenvalue* of $A$, and $v$ is the corresponding *eigenvector*.
+
+Thus, an eigenvector of $A$ is a nonzero vector $v$ such that when the map $A$ is
+applied, $v$ is merely scaled.
+
+The next figure shows two eigenvectors (blue arrows) and their images under
+$A$ (red arrows).
+
+As expected, the image $Av$ of each $v$ is just a scaled version of the original
+
+```{code-cell} ipython3
+:tags: [output_scroll]
+
+from numpy.linalg import eig
+
+A = [[1, 2],
+ [2, 1]]
+A = np.array(A)
+evals, evecs = eig(A)
+evecs = evecs[:, 0], evecs[:, 1]
+
+fig, ax = plt.subplots(figsize=(10, 8))
+# Set the axes through the origin
+for spine in ['left', 'bottom']:
+ ax.spines[spine].set_position('zero')
+for spine in ['right', 'top']:
+ ax.spines[spine].set_color('none')
+# ax.grid(alpha=0.4)
+
+xmin, xmax = -3, 3
+ymin, ymax = -3, 3
+ax.set(xlim=(xmin, xmax), ylim=(ymin, ymax))
+
+# Plot each eigenvector
+for v in evecs:
+ ax.annotate('', xy=v, xytext=(0, 0),
+ arrowprops=dict(facecolor='blue',
+ shrink=0,
+ alpha=0.6,
+ width=0.5))
+
+# Plot the image of each eigenvector
+for v in evecs:
+ v = A @ v
+ ax.annotate('', xy=v, xytext=(0, 0),
+ arrowprops=dict(facecolor='red',
+ shrink=0,
+ alpha=0.6,
+ width=0.5))
+
+# Plot the lines they run through
+x = np.linspace(xmin, xmax, 3)
+for v in evecs:
+ a = v[1] / v[0]
+ ax.plot(x, a * x, 'b-', lw=0.4)
+
+plt.show()
+```
+
++++ {"user_expressions": []}
+
+### Complex values
+
+So far our definition of eigenvalues and eigenvectors seems straightforward.
+
+There is one complication we haven't mentioned yet:
+
+When solving $Av = \lambda v$,
+
+* $\lambda$ is allowed to be a complex number and
+* $v$ is allowed to be an $n$-vector of complex numbers.
+
+We will see some examples below.
+
+### Some mathematical details
+
+We note some mathematical details for more advanced readers.
+
+(Other readers can skip to the next section.)
+
+The eigenvalue equation is equivalent to $(A - \lambda I) v = 0$.
+
+This equation has a nonzero solution $v$ only when the columns of $A - \lambda I$ are linearly dependent.
+
+This in turn is equivalent to stating the determinant is zero.
+
+Hence, to find all eigenvalues, we can look for $\lambda$ such that the
+determinant of $A - \lambda I$ is zero.
+
+This problem can be expressed as one of solving for the roots of a polynomial
+in $\lambda$ of degree $n$.
+
+This in turn implies the existence of $n$ solutions in the complex
+plane, although some might be repeated.
+
+### Facts
+
+Some nice facts about the eigenvalues of a square matrix $A$ are as follows:
+
+1. the determinant of $A$ equals the product of the eigenvalues
+2. the trace of $A$ (the sum of the elements on the principal diagonal) equals the sum of the eigenvalues
+3. if $A$ is symmetric, then all of its eigenvalues are real
+4. if $A$ is invertible and $\lambda_1, \ldots, \lambda_n$ are its eigenvalues, then the eigenvalues of $A^{-1}$ are $1/\lambda_1, \ldots, 1/\lambda_n$.
+
+A corollary of the last statement is that a matrix is invertible if and only if all its eigenvalues are nonzero.
+
+### Computation
+
+Using NumPy, we can solve for the eigenvalues and eigenvectors of a matrix as follows
+
+```{code-cell} ipython3
+from numpy.linalg import eig
+
+A = ((1, 2),
+ (2, 1))
+
+A = np.array(A)
+evals, evecs = eig(A)
+evals # eigenvalues
+```
+
+```{code-cell} ipython3
+evecs # eigenvectors
+```
+
++++ {"user_expressions": []}
+
+Note that the *columns* of `evecs` are the eigenvectors.
+
+Since any scalar multiple of an eigenvector is an eigenvector with the same
+eigenvalue (which can be verified), the `eig` routine normalizes the length of each eigenvector
+to one.
+
+The eigenvectors and eigenvalues of a map $A$ determine how a vector $v$ is transformed when we repeatedly multiply by $A$.
+
+This is discussed further later.
+
+
+(la_neumann)=
+## The Neumann Series Lemma
+
+```{index} single: Neumann's Lemma
+```
+
+In this section we present a famous result about series of matrices that has
+many applications in economics.
+
+### Scalar series
+
+Here's a fundamental result about series:
+
+If $a$ is a number and $|a| < 1$, then
+
+```{math}
+:label: gp_sum
+
+ \sum_{k=0}^{\infty} a^k =\frac{1}{1-a} = (1 - a)^{-1}
+
+```
+
+For a one-dimensional linear equation $x = ax + b$ where x is unknown we can thus conclude that the solution $x^{*}$ is given by:
+
+$$
+ x^{*} = \frac{b}{1-a} = \sum_{k=0}^{\infty} a^k b
+$$
+
+### Matrix series
+
+A generalization of this idea exists in the matrix setting.
+
+Consider the system of equations $x = Ax + b$ where $A$ is an $n \times n$
+square matrix and $x$ and $b$ are both column vectors in $\mathbb{R}^n$.
+
+Using matrix algebra we can conclude that the solution to this system of equations will be given by:
+
+```{math}
+:label: neumann_eqn
+
+ x^{*} = (I-A)^{-1}b
+
+```
+
+What guarantees the existence of a unique vector $x^{*}$ that satisfies
+{eq}`neumann_eqn`?
+
+The following is a fundamental result in functional analysis that generalizes
+{eq}`gp_sum` to a multivariate case.
+
+(neumann_series_lemma)=
+```{prf:Theorem} Neumann Series Lemma
+:label: neumann_series_lemma
+
+Let $A$ be a square matrix and let $A^k$ be the $k$-th power of $A$.
+
+Let $r(A)$ be the **spectral radius** of $A$, defined as $\max_i |\lambda_i|$, where
+
+* $\{\lambda_i\}_i$ is the set of eigenvalues of $A$ and
+* $|\lambda_i|$ is the modulus of the complex number $\lambda_i$
+
+Neumann's Theorem states the following: If $r(A) < 1$, then $I - A$ is invertible, and
+
+$$
+(I - A)^{-1} = \sum_{k=0}^{\infty} A^k
+$$
+```
+
+We can see the Neumann Series Lemma in action in the following example.
+
+```{code-cell} ipython3
+A = np.array([[0.4, 0.1],
+ [0.7, 0.2]])
+
+evals, evecs = eig(A) # finding eigenvalues and eigenvectors
+
+r = max(abs(λ) for λ in evals) # compute spectral radius
+print(r)
+```
+
+The spectral radius $r(A)$ obtained is less than 1.
+
+Thus, we can apply the Neumann Series Lemma to find $(I-A)^{-1}$.
+
+```{code-cell} ipython3
+I = np.identity(2) # 2 x 2 identity matrix
+B = I - A
+```
+
+```{code-cell} ipython3
+B_inverse = np.linalg.inv(B) # direct inverse method
+```
+
+```{code-cell} ipython3
+A_sum = np.zeros((2, 2)) # power series sum of A
+A_power = I
+for i in range(50):
+ A_sum += A_power
+ A_power = A_power @ A
+```
+
+Let's check equality between the sum and the inverse methods.
+
+```{code-cell} ipython3
+np.allclose(A_sum, B_inverse)
+```
+
+Although we truncate the infinite sum at $k = 50$, both methods give us the same
+result which illustrates the result of the Neumann Series Lemma.
+
+
+## Exercises
+
+```{exercise}
+:label: eig1_ex1
+
+Power iteration is a method for finding the greatest absolute eigenvalue of a diagonalizable matrix.
+
+The method starts with a random vector $b_0$ and repeatedly applies the matrix $A$ to it
+
+$$
+b_{k+1}=\frac{A b_k}{\left\|A b_k\right\|}
+$$
+
+A thorough discussion of the method can be found [here](https://pythonnumericalmethods.berkeley.edu/notebooks/chapter15.02-The-Power-Method.html).
+
+In this exercise, first implement the power iteration method and use it to find the greatest absolute eigenvalue and its corresponding eigenvector.
+
+Then visualize the convergence.
+```
+
+```{solution-start} eig1_ex1
+:class: dropdown
+```
+
+Here is one solution.
+
+We start by looking into the distance between the eigenvector approximation and the true eigenvector.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: Power iteration
+ name: pow-dist
+---
+# Define a matrix A
+A = np.array([[1, 0, 3],
+ [0, 2, 0],
+ [3, 0, 1]])
+
+num_iters = 20
+
+# Define a random starting vector b
+b = np.random.rand(A.shape[1])
+
+# Get the leading eigenvector of matrix A
+eigenvector = np.linalg.eig(A)[1][:, 0]
+
+errors = []
+res = []
+
+# Power iteration loop
+for i in range(num_iters):
+ # Multiply b by A
+ b = A @ b
+ # Normalize b
+ b = b / np.linalg.norm(b)
+ # Append b to the list of eigenvector approximations
+ res.append(b)
+ err = np.linalg.norm(np.array(b)
+ - eigenvector)
+ errors.append(err)
+
+greatest_eigenvalue = np.dot(A @ b, b) / np.dot(b, b)
+print(f'The approximated greatest absolute eigenvalue is \
+ {greatest_eigenvalue:.2f}')
+print('The real eigenvalue is', np.linalg.eig(A)[0])
+
+# Plot the eigenvector approximations for each iteration
+plt.figure(figsize=(10, 6))
+plt.xlabel('iterations')
+plt.ylabel('error')
+_ = plt.plot(errors)
+```
+
++++ {"user_expressions": []}
+
+Then we can look at the trajectory of the eigenvector approximation.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: Power iteration trajectory
+ name: pow-trajectory
+---
+# Set up the figure and axis for 3D plot
+fig = plt.figure()
+ax = fig.add_subplot(111, projection='3d')
+
+# Plot the eigenvectors
+ax.scatter(eigenvector[0],
+ eigenvector[1],
+ eigenvector[2],
+ color='r', s=80)
+
+for i, vec in enumerate(res):
+ ax.scatter(vec[0], vec[1], vec[2],
+ color='b',
+ alpha=(i+1)/(num_iters+1),
+ s=80)
+
+ax.set_xlabel('x')
+ax.set_ylabel('y')
+ax.set_zlabel('z')
+ax.tick_params(axis='both', which='major', labelsize=7)
+
+points = [plt.Line2D([0], [0], linestyle='none',
+ c=i, marker='o') for i in ['r', 'b']]
+ax.legend(points, ['actual eigenvector',
+ r'approximated eigenvector ($b_k$)'])
+ax.set_box_aspect(aspect=None, zoom=0.8)
+
+plt.show()
+```
+
++++ {"user_expressions": []}
+
+```{solution-end}
+```
+
+```{exercise}
+:label: eig1_ex2
+
+We have discussed the trajectory of the vector $v$ after being transformed by $A$.
+
+Consider the matrix $A = \begin{bmatrix} 1 & 2 \\ 1 & 1 \end{bmatrix}$ and the vector $v = \begin{bmatrix} 2 \\ -2 \end{bmatrix}$.
+
+Try to compute the trajectory of $v$ after being transformed by $A$ for $n=4$ iterations and plot the result.
+
+```
+
+```{solution-start} eig1_ex2
+:class: dropdown
+```
+
+```{code-cell} ipython3
+A = np.array([[1, 2],
+ [1, 1]])
+v = (0.4, -0.4)
+n = 11
+
+# Compute eigenvectors and eigenvalues
+eigenvalues, eigenvectors = np.linalg.eig(A)
+
+print(f'eigenvalues:\n {eigenvalues}')
+print(f'eigenvectors:\n {eigenvectors}')
+
+plot_series(A, v, n)
+```
+
++++ {"user_expressions": []}
+
+The result seems to converge to the eigenvector of $A$ with the largest eigenvalue.
+
+Let's use a [vector field](https://en.wikipedia.org/wiki/Vector_field) to visualize the transformation brought by A.
+
+(This is a more advanced topic in linear algebra, please step ahead if you are comfortable with the math.)
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: Convergence towards eigenvectors
+ name: eigen-conv
+---
+# Create a grid of points
+x, y = np.meshgrid(np.linspace(-5, 5, 15),
+ np.linspace(-5, 5, 20))
+
+# Apply the matrix A to each point in the vector field
+vec_field = np.stack([x, y])
+u, v = np.tensordot(A, vec_field, axes=1)
+
+# Plot the transformed vector field
+c = plt.streamplot(x, y, u - x, v - y,
+ density=1, linewidth=None, color='#A23BEC')
+c.lines.set_alpha(0.5)
+c.arrows.set_alpha(0.5)
+
+# Draw eigenvectors
+origin = np.zeros((2, len(eigenvectors)))
+parameters = {'color': ['b', 'g'], 'angles': 'xy',
+ 'scale_units': 'xy', 'scale': 0.1, 'width': 0.01}
+plt.quiver(*origin, eigenvectors[0],
+ eigenvectors[1], **parameters)
+plt.quiver(*origin, - eigenvectors[0],
+ - eigenvectors[1], **parameters)
+
+colors = ['b', 'g']
+lines = [Line2D([0], [0], color=c, linewidth=3) for c in colors]
+labels = ["2.4 eigenspace", "0.4 eigenspace"]
+plt.legend(lines, labels, loc='center left',
+ bbox_to_anchor=(1, 0.5))
+
+plt.xlabel("x")
+plt.ylabel("y")
+plt.grid()
+plt.gca().set_aspect('equal', adjustable='box')
+plt.show()
+```
+
++++ {"user_expressions": []}
+
+Note that the vector field converges to the eigenvector of $A$ with the largest eigenvalue and diverges from the eigenvector of $A$ with the smallest eigenvalue.
+
+In fact, the eigenvectors are also the directions in which the matrix $A$ stretches or shrinks the space.
+
+Specifically, the eigenvector with the largest eigenvalue is the direction in which the matrix $A$ stretches the space the most.
+
+We will see more intriguing examples in the following exercise.
+
+```{solution-end}
+```
+
+```{exercise}
+:label: eig1_ex3
+
+{ref}`Previously `, we demonstrated the trajectory of the vector $v$ after being transformed by $A$ for three different matrices.
+
+Use the visualization in the previous exercise to explain the trajectory of the vector $v$ after being transformed by $A$ for the three different matrices.
+
+```
+
+
+```{solution-start} eig1_ex3
+:class: dropdown
+```
+
+Here is one solution
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: Vector fields of the three matrices
+ name: vector-field
+---
+figure, ax = plt.subplots(1, 3, figsize=(15, 5))
+A = np.array([[sqrt(3) + 1, -2],
+ [1, sqrt(3) - 1]])
+A = (1/(2*sqrt(2))) * A
+
+B = np.array([[sqrt(3) + 1, -2],
+ [1, sqrt(3) - 1]])
+B = (1/2) * B
+
+C = np.array([[sqrt(3) + 1, -2],
+ [1, sqrt(3) - 1]])
+C = (1/sqrt(2)) * C
+
+examples = [A, B, C]
+
+for i, example in enumerate(examples):
+ M = example
+
+ # Compute right eigenvectors and eigenvalues
+ eigenvalues, eigenvectors = np.linalg.eig(M)
+ print(f'Example {i+1}:\n')
+ print(f'eigenvalues:\n {eigenvalues}')
+ print(f'eigenvectors:\n {eigenvectors}\n')
+
+ eigenvalues_real = eigenvalues.real
+ eigenvectors_real = eigenvectors.real
+
+ # Create a grid of points
+ x, y = np.meshgrid(np.linspace(-20, 20, 15),
+ np.linspace(-20, 20, 20))
+
+ # Apply the matrix A to each point in the vector field
+ vec_field = np.stack([x, y])
+ u, v = np.tensordot(M, vec_field, axes=1)
+
+ # Plot the transformed vector field
+ c = ax[i].streamplot(x, y, u - x, v - y, density=1,
+ linewidth=None, color='#A23BEC')
+ c.lines.set_alpha(0.5)
+ c.arrows.set_alpha(0.5)
+
+ # Draw eigenvectors
+ parameters = {'color': ['b', 'g'], 'angles': 'xy',
+ 'scale_units': 'xy', 'scale': 1,
+ 'width': 0.01, 'alpha': 0.5}
+ origin = np.zeros((2, len(eigenvectors)))
+ ax[i].quiver(*origin, eigenvectors_real[0],
+ eigenvectors_real[1], **parameters)
+ ax[i].quiver(*origin,
+ - eigenvectors_real[0],
+ - eigenvectors_real[1],
+ **parameters)
+
+ ax[i].set_xlabel("x-axis")
+ ax[i].set_ylabel("y-axis")
+ ax[i].grid()
+ ax[i].set_aspect('equal', adjustable='box')
+
+plt.show()
+```
+
++++ {"user_expressions": []}
+
+The vector fields explain why we observed the trajectories of the vector $v$ multiplied by $A$ iteratively before.
+
+The pattern demonstrated here is because we have complex eigenvalues and eigenvectors.
+
+We can plot the complex plane for one of the matrices using `Arrow3D` class retrieved from [stackoverflow](https://stackoverflow.com/questions/22867620/putting-arrowheads-on-vectors-in-a-3d-plot).
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: 3D plot of the vector field
+ name: 3d-vector-field
+---
+class Arrow3D(FancyArrowPatch):
+ def __init__(self, xs, ys, zs, *args, **kwargs):
+ super().__init__((0, 0), (0, 0), *args, **kwargs)
+ self._verts3d = xs, ys, zs
+
+ def do_3d_projection(self):
+ xs3d, ys3d, zs3d = self._verts3d
+ xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d,
+ self.axes.M)
+ self.set_positions((0.1*xs[0], 0.1*ys[0]),
+ (0.1*xs[1], 0.1*ys[1]))
+
+ return np.min(zs)
+
+
+eigenvalues, eigenvectors = np.linalg.eig(A)
+
+# Create meshgrid for vector field
+x, y = np.meshgrid(np.linspace(-2, 2, 15),
+ np.linspace(-2, 2, 15))
+
+# Calculate vector field (real and imaginary parts)
+u_real = A[0][0] * x + A[0][1] * y
+v_real = A[1][0] * x + A[1][1] * y
+u_imag = np.zeros_like(x)
+v_imag = np.zeros_like(y)
+
+# Create 3D figure
+fig = plt.figure()
+ax = fig.add_subplot(111, projection='3d')
+vlength = np.linalg.norm(eigenvectors)
+ax.quiver(x, y, u_imag, u_real-x, v_real-y, v_imag-u_imag,
+ colors='b', alpha=0.3, length=.2,
+ arrow_length_ratio=0.01)
+
+arrow_prop_dict = dict(mutation_scale=5,
+ arrowstyle='-|>', shrinkA=0, shrinkB=0)
+
+# Plot 3D eigenvectors
+for c, i in zip(['b', 'g'], [0, 1]):
+ a = Arrow3D([0, eigenvectors[0][i].real],
+ [0, eigenvectors[1][i].real],
+ [0, eigenvectors[1][i].imag],
+ color=c, **arrow_prop_dict)
+ ax.add_artist(a)
+
+# Set axis labels and title
+ax.set_xlabel('x')
+ax.set_ylabel('y')
+ax.set_zlabel('Im')
+ax.set_box_aspect(aspect=None, zoom=0.8)
+
+plt.draw()
+plt.show()
+```
+
++++ {"user_expressions": []}
+
+```{solution-end}
+```
diff --git a/content/lectures/eigen_II.ipynb b/book/_build/html/_sources/eigen_II.ipynb
similarity index 59%
rename from content/lectures/eigen_II.ipynb
rename to book/_build/html/_sources/eigen_II.ipynb
index c272af1..5e01680 100644
--- a/content/lectures/eigen_II.ipynb
+++ b/book/_build/html/_sources/eigen_II.ipynb
@@ -2,18 +2,12 @@
"cells": [
{
"cell_type": "markdown",
- "id": "cdd061a2",
- "metadata": {
- "user_expressions": []
- },
+ "id": "db831433",
+ "metadata": {},
"source": [
- "# Spectral Theory\n",
+ "# The Perron-Frobenius Theorem\n",
"\n",
- "```{index} single: Spectral Theory\n",
- "```\n",
- "\n",
- "```{contents} Contents\n",
- ":depth: 2\n",
+ "```{index} single: The Perron-Frobenius Theorem\n",
"```\n",
"\n",
"In addition to what's in Anaconda, this lecture will need the following libraries:"
@@ -22,7 +16,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "49e26923",
+ "id": "e75946f7",
"metadata": {
"tags": [
"hide-output"
@@ -30,24 +24,17 @@
},
"outputs": [],
"source": [
- "%pip install graphviz quantecon"
+ "%pip install quantecon"
]
},
{
"cell_type": "markdown",
- "id": "7e9441fc",
+ "id": "d984f84b",
"metadata": {},
"source": [
- "```{admonition} graphviz\n",
- ":class: warning\n",
- "If you are running this lecture locally it requires [graphviz](https://www.graphviz.org)\n",
- "to be installed on your computer. Installation instructions for graphviz can be found\n",
- "[here](https://www.graphviz.org/download/) \n",
- "```\n",
- "\n",
"In this lecture we will begin with the foundational concepts in spectral theory.\n",
"\n",
- "Then we will explore the Perron-Frobenius Theorem and the Neumann Series Lemma, and connect them to applications in Markov chains and networks. \n",
+ "Then we will explore the Perron-Frobenius theorem and connect it to applications in Markov chains and networks.\n",
"\n",
"We will use the following imports:"
]
@@ -55,21 +42,19 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "81ce3eee",
+ "id": "11f5c183",
"metadata": {},
"outputs": [],
"source": [
- "import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"from numpy.linalg import eig\n",
"import scipy as sp\n",
- "import graphviz as gv\n",
"import quantecon as qe"
]
},
{
"cell_type": "markdown",
- "id": "4164bdc6",
+ "id": "5f3c4b8d",
"metadata": {},
"source": [
"## Nonnegative matrices\n",
@@ -78,11 +63,9 @@
"\n",
"Nonnegative matrices have several special and useful properties.\n",
"\n",
- "In this section we discuss some of them --- in particular, the connection\n",
+ "In this section we will discuss some of them --- in particular, the connection\n",
"between nonnegativity and eigenvalues.\n",
"\n",
- "Let $a^{k}_{ij}$ be element $(i,j)$ of $A^k$.\n",
- "\n",
"An $n \\times m$ matrix $A$ is called **nonnegative** if every element of $A$\n",
"is nonnegative, i.e., $a_{ij} \\geq 0$ for every $i,j$.\n",
"\n",
@@ -91,50 +74,70 @@
"(irreducible)=\n",
"### Irreducible matrices\n",
"\n",
- "We have (informally) introduced irreducible matrices in the Markov chain lecture (TODO: link to Markov chain lecture).\n",
+ "We introduced irreducible matrices in the [Markov chain lecture](mc_irreducible).\n",
"\n",
- "Here we will introduce this concept formally.\n",
+ "Here we generalize this concept:\n",
"\n",
- "$A$ is called **irreducible** if for *each* $(i,j)$ there is an integer $k \\geq 0$ such that $a^{k}_{ij} > 0$.\n",
+ "Let $a^{k}_{ij}$ be element $(i,j)$ of $A^k$.\n",
"\n",
- "A matrix $A$ that is not irreducible is called reducible.\n",
+ "An $n \\times n$ nonnegative matrix $A$ is called irreducible if $A + A^2 + A^3 + \\cdots \\gg 0$, where $\\gg 0$ indicates that every element in $A$ is strictly positive.\n",
"\n",
- "Here are some examples to illustrate this further.\n",
+ "In other words, for each $i,j$ with $1 \\leq i, j \\leq n$, there exists a $k \\geq 0$ such that $a^{k}_{ij} > 0$.\n",
"\n",
- "1. $A = \\begin{bmatrix} 0.5 & 0.1 \\\\ 0.2 & 0.2 \\end{bmatrix}$ is irreducible since $a_{ij}>0$ for all $(i,j)$.\n",
+ "```{prf:example}\n",
+ ":label: eigen2_ex_irr\n",
"\n",
- "2. $A = \\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix}$ is irreducible since $a_{12},a_{21} >0$ and $a^{2}_{11},a^{2}_{22} >0$.\n",
+ "Here are some examples to illustrate this further:\n",
"\n",
- "3. $A = \\begin{bmatrix} 1 & 0 \\\\ 0 & 1 \\end{bmatrix}$ is reducible since $A^k = A$ for all $k \\geq 0$ and thus\n",
- " $a^{k}_{12},a^{k}_{21} = 0$ for all $k \\geq 0$.\n",
+ "$$\n",
+ "A = \\begin{bmatrix} 0.5 & 0.1 \\\\ \n",
+ " 0.2 & 0.2 \n",
+ "\\end{bmatrix}\n",
+ "$$\n",
"\n",
- "### Primitive matrices\n",
+ "$A$ is irreducible since $a_{ij}>0$ for all $(i,j)$.\n",
"\n",
- "Let $A$ be a square nonnegative matrix and let $A^k$ be the $k^{th}$ power of $A$.\n",
+ "$$\n",
+ "B = \\begin{bmatrix} 0 & 1 \\\\ \n",
+ " 1 & 0 \n",
+ "\\end{bmatrix}\n",
+ ", \\quad\n",
+ "B^2 = \\begin{bmatrix} 1 & 0 \\\\ \n",
+ " 0 & 1\n",
+ "\\end{bmatrix}\n",
+ "$$\n",
"\n",
- "A matrix is considered **primitive** if there exists a $k \\in \\mathbb{N}$ such that $A^k$ is everywhere positive.\n",
+ "$B$ is irreducible since $B + B^2$ is a matrix of ones.\n",
"\n",
- "It means that $A$ is called primitive if there is an integer $k \\geq 0$ such that $a^{k}_{ij} > 0$ for *all* $(i,j)$.\n",
+ "$$\n",
+ "C = \\begin{bmatrix} 1 & 0 \\\\ \n",
+ " 0 & 1 \n",
+ "\\end{bmatrix}\n",
+ "$$\n",
"\n",
- "We can see that if a matrix is primitive, then it implies the matrix is irreducible.\n",
+ "$C$ is not irreducible since $C^k = C$ for all $k \\geq 0$ and thus\n",
+ " $c^{k}_{12},c^{k}_{21} = 0$ for all $k \\geq 0$.\n",
+ "```\n",
"\n",
- "This is because if there exists an $A^k$ such that $a^{k}_{ij} > 0$ for all $(i,j)$, then it guarantees the same property for ${k+1}^th, {k+2}^th ... {k+n}^th$ iterations.\n",
+ "### Left eigenvectors\n",
"\n",
- "In other words, a primitive matrix is both irreducible and aperiodic as aperiodicity requires a state to be visited with a guarantee of returning to itself after a certain amount of iterations.\n",
+ "Recall that we previously discussed eigenvectors in {ref}`Eigenvalues and Eigenvectors `.\n",
"\n",
- "### Left eigenvectors\n",
+ "In particular, $\\lambda$ is an eigenvalue of $A$ and $v$ is an eigenvector of $A$ if $v$ is nonzero and satisfy\n",
+ "\n",
+ "$$\n",
+ "Av = \\lambda v.\n",
+ "$$\n",
"\n",
- "We have previously discussed right (ordinary) eigenvectors $Av = \\lambda v$.\n",
+ "In this section we introduce left eigenvectors.\n",
"\n",
- "Here we introduce left eigenvectors.\n",
+ "To avoid confusion, what we previously referred to as \"eigenvectors\" will be called \"right eigenvectors\".\n",
"\n",
"Left eigenvectors will play important roles in what follows, including that of stochastic steady states for dynamic models under a Markov assumption.\n",
"\n",
- "We will talk more about this later, but for now, let's define left eigenvectors.\n",
- "\n",
- "A vector $w$ is called a left eigenvector of $A$ if $w$ is an eigenvector of $A^T$.\n",
+ "A vector $w$ is called a left eigenvector of $A$ if $w$ is a right eigenvector of $A^\\top$.\n",
"\n",
- "In other words, if $w$ is a left eigenvector of matrix A, then $A^T w = \\lambda w$, where $\\lambda$ is the eigenvalue associated with the left eigenvector $v$.\n",
+ "In other words, if $w$ is a left eigenvector of matrix $A$, then $A^\\top w = \\lambda w$, where $\\lambda$ is the eigenvalue associated with the left eigenvector $v$.\n",
"\n",
"This hints at how to compute left eigenvectors"
]
@@ -142,83 +145,77 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "d8b97125",
+ "id": "763169b2",
"metadata": {},
"outputs": [],
"source": [
- "A = np.array([[3, 2], \n",
+ "A = np.array([[3, 2],\n",
" [1, 4]])\n",
"\n",
- "# Compute right eigenvectors and eigenvalues\n",
- "λ_r, v = eig(A)\n",
+ "# Compute eigenvalues and right eigenvectors\n",
+ "λ, v = eig(A)\n",
"\n",
- "# Compute left eigenvectors and eigenvalues\n",
- "λ_l, w = eig(A.T)\n",
+ "# Compute eigenvalues and left eigenvectors\n",
+ "λ, w = eig(A.T)\n",
"\n",
- "print(\"Right Eigenvalues:\")\n",
- "print(λ_r)\n",
- "print(\"\\nRight Eigenvectors:\")\n",
- "print(v)\n",
- "print(\"\\nLeft Eigenvalues:\")\n",
- "print(λ_l)\n",
- "print(\"\\nLeft Eigenvectors:\")\n",
- "print(w)"
+ "# Keep 5 decimals\n",
+ "np.set_printoptions(precision=5)\n",
+ "\n",
+ "print(f\"The eigenvalues of A are:\\n {λ}\\n\")\n",
+ "print(f\"The corresponding right eigenvectors are: \\n {v[:,0]} and {-v[:,1]}\\n\")\n",
+ "print(f\"The corresponding left eigenvectors are: \\n {w[:,0]} and {-w[:,1]}\\n\")"
]
},
{
"cell_type": "markdown",
- "id": "b9ea57bb",
+ "id": "5bf945bc",
"metadata": {},
"source": [
- "We can use `scipy.linalg.eig` with argument `left=True` to find left eigenvectors directly"
+ "We can also use `scipy.linalg.eig` with argument `left=True` to find left eigenvectors directly"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "cbfde1c1",
+ "id": "88671da4",
"metadata": {},
"outputs": [],
"source": [
"eigenvals, ε, e = sp.linalg.eig(A, left=True)\n",
"\n",
- "print(\"Right Eigenvalues:\")\n",
- "print(λ_r)\n",
- "print(\"\\nRight Eigenvectors:\")\n",
- "print(v)\n",
- "print(\"\\nLeft Eigenvalues:\")\n",
- "print(λ_l)\n",
- "print(\"\\nLeft Eigenvectors:\")\n",
- "print(w)"
+ "print(f\"The eigenvalues of A are:\\n {eigenvals.real}\\n\")\n",
+ "print(f\"The corresponding right eigenvectors are: \\n {e[:,0]} and {-e[:,1]}\\n\")\n",
+ "print(f\"The corresponding left eigenvectors are: \\n {ε[:,0]} and {-ε[:,1]}\\n\")"
]
},
{
"cell_type": "markdown",
- "id": "91429576",
+ "id": "18adb7ee",
"metadata": {},
"source": [
- "Note that the eigenvalues for both left and right eigenvectors are the same, but the eigenvectors themselves are different.\n",
+ "The eigenvalues are the same while the eigenvectors themselves are different.\n",
+ "\n",
+ "(Also note that we are taking the nonnegative value of the eigenvector of {ref}`dominant eigenvalue `, this is because `eig` automatically normalizes the eigenvectors.)\n",
"\n",
- "We can then take transpose to obtain $A^T w = \\lambda w$ and obtain $w^T A= \\lambda w^T$.\n",
+ "We can then take transpose to obtain $A^\\top w = \\lambda w$ and obtain $w^\\top A= \\lambda w^\\top$.\n",
"\n",
"This is a more common expression and where the name left eigenvectors originates.\n",
"\n",
"(perron-frobe)=\n",
- "### The Perron-Frobenius Theorem\n",
+ "### The Perron-Frobenius theorem\n",
"\n",
- "For a nonnegative matrix $A$ the behavior of $A^k$ as $k \\to \\infty$ is controlled by the eigenvalue with the largest\n",
+ "For a square nonnegative matrix $A$, the behavior of $A^k$ as $k \\to \\infty$ is controlled by the eigenvalue with the largest\n",
"absolute value, often called the **dominant eigenvalue**.\n",
"\n",
- "For a matrix $A$, the Perron-Frobenius Theorem characterizes certain\n",
- "properties of the dominant eigenvalue and its corresponding eigenvector when\n",
- "$A$ is a nonnegative square matrix.\n",
+ "For any such matrix $A$, the Perron-Frobenius theorem characterizes certain\n",
+ "properties of the dominant eigenvalue and its corresponding eigenvector.\n",
"\n",
"```{prf:Theorem} Perron-Frobenius Theorem\n",
":label: perron-frobenius\n",
"\n",
"If a matrix $A \\geq 0$ then,\n",
"\n",
- "1. the dominant eigenvalue of $A$, $r(A)$, is real-valued and nonnegative. \n",
+ "1. the dominant eigenvalue of $A$, $r(A)$, is real-valued and nonnegative.\n",
"2. for any other eigenvalue (possibly complex) $\\lambda$ of $A$, $|\\lambda| \\leq r(A)$.\n",
"3. we can find a nonnegative and nonzero eigenvector $v$ such that $Av = r(A)v$.\n",
"\n",
@@ -227,11 +224,7 @@
"4. the eigenvector $v$ associated with the eigenvalue $r(A)$ is strictly positive.\n",
"5. there exists no other positive eigenvector $v$ (except scalar multiples of $v$) associated with $r(A)$.\n",
"\n",
- "If $A$ is primitive then,\n",
- "\n",
- "6. the inequality $|\\lambda| \\leq r(A)$ is **strict** for all eigenvalues $\\lambda$ of $A$ distinct from $r(A)$, and\n",
- "7. with $v$ and $w$ normalized so that the inner product of $w$ and $v = 1$, we have\n",
- "$ r(A)^{-m} A^m$ converges to $v w^{\\top}$ when $m \\rightarrow \\infty$. $v w^{\\top}$ is called the **Perron projection** of $A$.\n",
+ "(More of the Perron-Frobenius theorem about primitive matrices will be introduced {ref}`below `.)\n",
"```\n",
"\n",
"(This is a relatively simple version of the theorem --- for more details see\n",
@@ -243,26 +236,26 @@
"\n",
"Now let's consider examples for each case.\n",
"\n",
- "#### Example 1: irreducible matrix\n",
+ "#### Example: irreducible matrix\n",
"\n",
- "Consider the following irreducible matrix A:"
+ "Consider the following irreducible matrix $A$:"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "4ed1be06",
+ "id": "24135c2f",
"metadata": {},
"outputs": [],
"source": [
- "A = np.array([[0, 1, 0], \n",
- " [.5, 0, .5], \n",
+ "A = np.array([[0, 1, 0],\n",
+ " [.5, 0, .5],\n",
" [0, 1, 0]])"
]
},
{
"cell_type": "markdown",
- "id": "ac576dd9",
+ "id": "ab825569",
"metadata": {},
"source": [
"We can compute the dominant eigenvalue and the corresponding eigenvector"
@@ -271,7 +264,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "100f9d99",
+ "id": "451e5efa",
"metadata": {},
"outputs": [],
"source": [
@@ -280,10 +273,10 @@
},
{
"cell_type": "markdown",
- "id": "91159750",
+ "id": "8320a0cc",
"metadata": {},
"source": [
- "Now we can go through our checklist to verify the claims of the Perron-Frobenius Theorem for the irreducible matrix A:\n",
+ "Now we can see the claims of the Perron-Frobenius theorem holds for the irreducible matrix $A$:\n",
"\n",
"1. The dominant eigenvalue is real-valued and non-negative.\n",
"2. All other eigenvalues have absolute values less than or equal to the dominant eigenvalue.\n",
@@ -291,20 +284,71 @@
"4. As the matrix is irreducible, the eigenvector associated with the dominant eigenvalue is strictly positive.\n",
"5. There exists no other positive eigenvector associated with the dominant eigenvalue.\n",
"\n",
- "#### Example 2: primitive matrix\n",
+ "(prim_matrices)=\n",
+ "### Primitive matrices\n",
+ "\n",
+ "We know that in real world situations it's hard for a matrix to be everywhere positive (although they have nice properties).\n",
+ "\n",
+ "The primitive matrices, however, can still give us helpful properties with looser definitions.\n",
+ "\n",
+ "Let $A$ be a square nonnegative matrix and let $A^k$ be the $k^{th}$ power of $A$.\n",
+ "\n",
+ "A matrix is called **primitive** if there exists a $k \\in \\mathbb{N}$ such that $A^k$ is everywhere positive.\n",
+ "\n",
+ "```{prf:example}\n",
+ ":label: eigen2_ex_prim\n",
+ "\n",
+ "Recall the examples given in irreducible matrices:\n",
+ "\n",
+ "$$\n",
+ "A = \\begin{bmatrix} 0.5 & 0.1 \\\\ \n",
+ " 0.2 & 0.2 \n",
+ "\\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "$A$ here is also a primitive matrix since $A^k$ is everywhere nonnegative for $k \\in \\mathbb{N}$.\n",
+ "\n",
+ "$$\n",
+ "B = \\begin{bmatrix} 0 & 1 \\\\ \n",
+ " 1 & 0 \n",
+ "\\end{bmatrix}\n",
+ ", \\quad\n",
+ "B^2 = \\begin{bmatrix} 1 & 0 \\\\ \n",
+ " 0 & 1\n",
+ "\\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "$B$ is irreducible but not primitive since there are always zeros in either principal diagonal or secondary diagonal.\n",
+ "```\n",
+ "\n",
+ "We can see that if a matrix is primitive, then it implies the matrix is irreducible but not vice versa.\n",
+ "\n",
+ "Now let's step back to the primitive matrices part of the Perron-Frobenius theorem\n",
"\n",
- "Consider the following primitive matrix B:"
+ "```{prf:Theorem} Continous of Perron-Frobenius Theorem\n",
+ ":label: con-perron-frobenius\n",
+ "\n",
+ "If $A$ is primitive then,\n",
+ "\n",
+ "6. the inequality $|\\lambda| \\leq r(A)$ is **strict** for all eigenvalues $\\lambda$ of $A$ distinct from $r(A)$, and\n",
+ "7. with $v$ and $w$ normalized so that the inner product of $w$ and $v = 1$, we have\n",
+ "$ r(A)^{-m} A^m$ converges to $v w^{\\top}$ when $m \\rightarrow \\infty$. The matrix $v w^{\\top}$ is called the **Perron projection** of $A$.\n",
+ "```\n",
+ "\n",
+ "#### Example 1: primitive matrix\n",
+ "\n",
+ "Consider the following primitive matrix $B$:"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "f0a62d44",
+ "id": "9714b55b",
"metadata": {},
"outputs": [],
"source": [
- "B = np.array([[0, 1, 1], \n",
- " [1, 0, 1], \n",
+ "B = np.array([[0, 1, 1],\n",
+ " [1, 0, 1],\n",
" [1, 1, 0]])\n",
"\n",
"np.linalg.matrix_power(B, 2)"
@@ -312,34 +356,16 @@
},
{
"cell_type": "markdown",
- "id": "c9ee1018",
+ "id": "47ab156b",
"metadata": {},
"source": [
- "We can compute the dominant eigenvalue and the corresponding eigenvector using the power iteration method as discussed {ref}`earlier`:"
+ "We compute the dominant eigenvalue and the corresponding eigenvector"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "8ad957e0",
- "metadata": {},
- "outputs": [],
- "source": [
- "num_iters = 20\n",
- "b = np.random.rand(B.shape[1])\n",
- "\n",
- "for i in range(num_iters):\n",
- " b = B @ b\n",
- " b = b / np.linalg.norm(b)\n",
- "\n",
- "dominant_eigenvalue = np.dot(B @ b, b) / np.dot(b, b)\n",
- "np.round(dominant_eigenvalue, 2)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "6430d7cb",
+ "id": "e1f7e578",
"metadata": {},
"outputs": [],
"source": [
@@ -348,12 +374,10 @@
},
{
"cell_type": "markdown",
- "id": "54bca13e",
- "metadata": {
- "user_expressions": []
- },
+ "id": "2d7f5a59",
+ "metadata": {},
"source": [
- "Now let's verify the claims of the Perron-Frobenius Theorem for the primitive matrix B:\n",
+ "Now let's give some examples to see if the claims of the Perron-Frobenius theorem hold for the primitive matrix $B$:\n",
"\n",
"1. The dominant eigenvalue is real-valued and non-negative.\n",
"2. All other eigenvalues have absolute values strictly less than the dominant eigenvalue.\n",
@@ -368,7 +392,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "b804c73e",
+ "id": "01f2acd0",
"metadata": {},
"outputs": [],
"source": [
@@ -403,7 +427,7 @@
" n_list = [1, 10, 100, 1000, 10000]\n",
"\n",
" for n in n_list:\n",
- " \n",
+ "\n",
" # Compute (A/r)^n\n",
" M_n = np.linalg.matrix_power(M/r, n)\n",
"\n",
@@ -412,15 +436,15 @@
"\n",
" # Calculate the norm of the difference matrix\n",
" diff_norm = np.linalg.norm(diff, 'fro')\n",
- " print(f\"n = {n}, norm of the difference: {diff_norm:.10f}\")\n",
+ " print(f\"n = {n}, error = {diff_norm:.10f}\")\n",
"\n",
"\n",
"A1 = np.array([[1, 2],\n",
" [1, 4]])\n",
"\n",
- "A2 = np.array([[0, 1, 1], \n",
- " [1, 0, 1], \n",
- " [1, 1, 0]])\n",
+ "A2 = np.array([[0, 1, 1],\n",
+ " [1, 0, 1],\n",
+ " [1, 1, 0]])\n",
"\n",
"A3 = np.array([[0.971, 0.029, 0.1, 1],\n",
" [0.145, 0.778, 0.077, 0.59],\n",
@@ -438,7 +462,7 @@
},
{
"cell_type": "markdown",
- "id": "29d8653a",
+ "id": "e6d81194",
"metadata": {},
"source": [
"The convergence is not observed in cases of non-primitive matrices.\n",
@@ -449,12 +473,12 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "3b6a21c5",
+ "id": "d7f2a270",
"metadata": {},
"outputs": [],
"source": [
- "B = np.array([[0, 1, 1], \n",
- " [1, 0, 0], \n",
+ "B = np.array([[0, 1, 1],\n",
+ " [1, 0, 0],\n",
" [1, 0, 0]])\n",
"\n",
"# This shows that the matrix is not primitive\n",
@@ -468,29 +492,29 @@
},
{
"cell_type": "markdown",
- "id": "827923e0",
+ "id": "34251903",
"metadata": {},
"source": [
"The result shows that the matrix is not primitive as it is not everywhere positive.\n",
"\n",
- "These examples show how the Perron-Frobenius Theorem relates to the eigenvalues and eigenvectors of positive matrices and the convergence of the power of matrices.\n",
+ "These examples show how the Perron-Frobenius theorem relates to the eigenvalues and eigenvectors of positive matrices and the convergence of the power of matrices.\n",
"\n",
- "In fact we have already seen the theorem in action before in {ref}`the markov chain lecture `.\n",
+ "In fact we have already seen the theorem in action before in {ref}`the Markov chain lecture `.\n",
"\n",
"(spec_markov)=\n",
- "#### Example 3: Connection to Markov chains\n",
+ "#### Example 2: connection to Markov chains\n",
"\n",
- "We are now prepared to bridge the languages spoken in the two lectures. \n",
+ "We are now prepared to bridge the languages spoken in the two lectures.\n",
"\n",
- "A primitive matrix is both irreducible (or strongly connected in the language of graph) and aperiodic.\n",
+ "A primitive matrix is both irreducible and aperiodic.\n",
"\n",
- "So Perron-Frobenius Theorem explains why both Imam and Temple matrix and Hamilton matrix converge to a stationary distribution, which is the Perron projection of the two matrices"
+ "So Perron-Frobenius theorem explains why both {ref}`Imam and Temple matrix ` and [Hamilton matrix](https://en.wikipedia.org/wiki/Hamiltonian_matrix) converge to a stationary distribution, which is the Perron projection of the two matrices"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "6976ad2e",
+ "id": "46125208",
"metadata": {},
"outputs": [],
"source": [
@@ -504,7 +528,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "dc21fb53",
+ "id": "a81e3800",
"metadata": {},
"outputs": [],
"source": [
@@ -516,7 +540,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "4e5ffd17",
+ "id": "c3581cf4",
"metadata": {},
"outputs": [],
"source": [
@@ -530,7 +554,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "c0fc7937",
+ "id": "1d8a6e2e",
"metadata": {},
"outputs": [],
"source": [
@@ -541,7 +565,7 @@
},
{
"cell_type": "markdown",
- "id": "8cc07782",
+ "id": "fb16f381",
"metadata": {},
"source": [
"We can also verify other properties hinted by Perron-Frobenius in these stochastic matrices."
@@ -549,7 +573,7 @@
},
{
"cell_type": "markdown",
- "id": "072e6b79",
+ "id": "55599735",
"metadata": {},
"source": [
"Another example is the relationship between convergence gap and convergence rate.\n",
@@ -558,6 +582,8 @@
"\n",
"This can be proven using what we have learned here.\n",
"\n",
+ "Please note that we use $\\mathbb{1}$ for a vector of ones in this lecture.\n",
+ "\n",
"With Markov model $M$ with state space $S$ and transition matrix $P$, we can write $P^t$ as\n",
"\n",
"$$\n",
@@ -566,7 +592,7 @@
"\n",
"This is proven in {cite}`sargent2023economic` and a nice discussion can be found [here](https://math.stackexchange.com/questions/2433997/can-all-matrices-be-decomposed-as-product-of-right-and-left-eigenvector).\n",
"\n",
- "In the formula $\\lambda_i$ is an eigenvalue of $P$ and $v_i$ and $w_i$ are the right and left eigenvectors corresponding to $\\lambda_i$. \n",
+ "In this formula $\\lambda_i$ is an eigenvalue of $P$ with corresponding right and left eigenvectors $v_i$ and $w_i$ .\n",
"\n",
"Premultiplying $P^t$ by arbitrary $\\psi \\in \\mathscr{D}(S)$ and rearranging now gives\n",
"\n",
@@ -574,15 +600,14 @@
"\\psi P^t-\\psi^*=\\sum_{i=1}^{n-1} \\lambda_i^t \\psi v_i w_i^{\\top}\n",
"$$\n",
"\n",
- "Recall that eigenvalues are ordered from smallest to largest from $i = 1 ... n$. \n",
+ "Recall that eigenvalues are ordered from smallest to largest from $i = 1 ... n$.\n",
"\n",
"As we have seen, the largest eigenvalue for a primitive stochastic matrix is one.\n",
"\n",
- "This can be proven using [Gershgorin Circle Theorem](https://en.wikipedia.org/wiki/Gershgorin_circle_theorem), \n",
+ "This can be proven using [Gershgorin Circle Theorem](https://en.wikipedia.org/wiki/Gershgorin_circle_theorem),\n",
"but it is out of the scope of this lecture.\n",
"\n",
- "So by the statement (6) of Perron-Frobenius Theorem, $\\lambda_i<1$ for all $i` to find the solution $x^{*}$ if it exists.\n",
"\n",
"```{exercise-end}\n",
"```\n",
@@ -827,7 +694,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "bfcc3219",
+ "id": "862b0677",
"metadata": {},
"outputs": [],
"source": [
@@ -843,16 +710,16 @@
},
{
"cell_type": "markdown",
- "id": "fc509d3d",
+ "id": "75dc1fa0",
"metadata": {},
"source": [
- "Since we have $r(A) < 1$ we can thus find the solution using the Neumann Series lemma."
+ "Since we have $r(A) < 1$ we can thus find the solution using the Neumann Series Lemma."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "60c4ec99",
+ "id": "dc46d4f1",
"metadata": {},
"outputs": [],
"source": [
@@ -869,7 +736,7 @@
},
{
"cell_type": "markdown",
- "id": "c3622489",
+ "id": "ad8f99ca",
"metadata": {},
"source": [
"```{solution-end}\n",
@@ -878,12 +745,53 @@
}
],
"metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.14.4"
+ }
+ },
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
- }
+ },
+ "source_map": [
+ 12,
+ 21,
+ 25,
+ 33,
+ 38,
+ 124,
+ 140,
+ 144,
+ 150,
+ 199,
+ 203,
+ 207,
+ 209,
+ 274,
+ 280,
+ 284,
+ 286,
+ 299,
+ 362,
+ 368,
+ 380,
+ 397,
+ 405,
+ 411,
+ 419,
+ 423,
+ 427,
+ 543,
+ 552,
+ 556,
+ 566
+ ]
},
"nbformat": 4,
"nbformat_minor": 5
-}
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/eigen_II.md b/book/_build/html/_sources/eigen_II.md
new file mode 100644
index 0000000..3d8c31a
--- /dev/null
+++ b/book/_build/html/_sources/eigen_II.md
@@ -0,0 +1,569 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.14.4
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+# The Perron-Frobenius Theorem
+
+```{index} single: The Perron-Frobenius Theorem
+```
+
+In addition to what's in Anaconda, this lecture will need the following libraries:
+
+```{code-cell} ipython3
+:tags: [hide-output]
+
+%pip install quantecon
+```
+
+In this lecture we will begin with the foundational concepts in spectral theory.
+
+Then we will explore the Perron-Frobenius theorem and connect it to applications in Markov chains and networks.
+
+We will use the following imports:
+
+```{code-cell} ipython3
+import numpy as np
+from numpy.linalg import eig
+import scipy as sp
+import quantecon as qe
+```
+
+## Nonnegative matrices
+
+Often, in economics, the matrix that we are dealing with is nonnegative.
+
+Nonnegative matrices have several special and useful properties.
+
+In this section we will discuss some of them --- in particular, the connection
+between nonnegativity and eigenvalues.
+
+An $n \times m$ matrix $A$ is called **nonnegative** if every element of $A$
+is nonnegative, i.e., $a_{ij} \geq 0$ for every $i,j$.
+
+We denote this as $A \geq 0$.
+
+(irreducible)=
+### Irreducible matrices
+
+We introduced irreducible matrices in the [Markov chain lecture](mc_irreducible).
+
+Here we generalize this concept:
+
+Let $a^{k}_{ij}$ be element $(i,j)$ of $A^k$.
+
+An $n \times n$ nonnegative matrix $A$ is called irreducible if $A + A^2 + A^3 + \cdots \gg 0$, where $\gg 0$ indicates that every element in $A$ is strictly positive.
+
+In other words, for each $i,j$ with $1 \leq i, j \leq n$, there exists a $k \geq 0$ such that $a^{k}_{ij} > 0$.
+
+```{prf:example}
+:label: eigen2_ex_irr
+
+Here are some examples to illustrate this further:
+
+$$
+A = \begin{bmatrix} 0.5 & 0.1 \\
+ 0.2 & 0.2
+\end{bmatrix}
+$$
+
+$A$ is irreducible since $a_{ij}>0$ for all $(i,j)$.
+
+$$
+B = \begin{bmatrix} 0 & 1 \\
+ 1 & 0
+\end{bmatrix}
+, \quad
+B^2 = \begin{bmatrix} 1 & 0 \\
+ 0 & 1
+\end{bmatrix}
+$$
+
+$B$ is irreducible since $B + B^2$ is a matrix of ones.
+
+$$
+C = \begin{bmatrix} 1 & 0 \\
+ 0 & 1
+\end{bmatrix}
+$$
+
+$C$ is not irreducible since $C^k = C$ for all $k \geq 0$ and thus
+ $c^{k}_{12},c^{k}_{21} = 0$ for all $k \geq 0$.
+```
+
+### Left eigenvectors
+
+Recall that we previously discussed eigenvectors in {ref}`Eigenvalues and Eigenvectors `.
+
+In particular, $\lambda$ is an eigenvalue of $A$ and $v$ is an eigenvector of $A$ if $v$ is nonzero and satisfy
+
+$$
+Av = \lambda v.
+$$
+
+In this section we introduce left eigenvectors.
+
+To avoid confusion, what we previously referred to as "eigenvectors" will be called "right eigenvectors".
+
+Left eigenvectors will play important roles in what follows, including that of stochastic steady states for dynamic models under a Markov assumption.
+
+A vector $w$ is called a left eigenvector of $A$ if $w$ is a right eigenvector of $A^\top$.
+
+In other words, if $w$ is a left eigenvector of matrix $A$, then $A^\top w = \lambda w$, where $\lambda$ is the eigenvalue associated with the left eigenvector $v$.
+
+This hints at how to compute left eigenvectors
+
+```{code-cell} ipython3
+A = np.array([[3, 2],
+ [1, 4]])
+
+# Compute eigenvalues and right eigenvectors
+λ, v = eig(A)
+
+# Compute eigenvalues and left eigenvectors
+λ, w = eig(A.T)
+
+# Keep 5 decimals
+np.set_printoptions(precision=5)
+
+print(f"The eigenvalues of A are:\n {λ}\n")
+print(f"The corresponding right eigenvectors are: \n {v[:,0]} and {-v[:,1]}\n")
+print(f"The corresponding left eigenvectors are: \n {w[:,0]} and {-w[:,1]}\n")
+```
+
+We can also use `scipy.linalg.eig` with argument `left=True` to find left eigenvectors directly
+
+```{code-cell} ipython3
+eigenvals, ε, e = sp.linalg.eig(A, left=True)
+
+print(f"The eigenvalues of A are:\n {eigenvals.real}\n")
+print(f"The corresponding right eigenvectors are: \n {e[:,0]} and {-e[:,1]}\n")
+print(f"The corresponding left eigenvectors are: \n {ε[:,0]} and {-ε[:,1]}\n")
+```
+
+The eigenvalues are the same while the eigenvectors themselves are different.
+
+(Also note that we are taking the nonnegative value of the eigenvector of {ref}`dominant eigenvalue `, this is because `eig` automatically normalizes the eigenvectors.)
+
+We can then take transpose to obtain $A^\top w = \lambda w$ and obtain $w^\top A= \lambda w^\top$.
+
+This is a more common expression and where the name left eigenvectors originates.
+
+(perron-frobe)=
+### The Perron-Frobenius theorem
+
+For a square nonnegative matrix $A$, the behavior of $A^k$ as $k \to \infty$ is controlled by the eigenvalue with the largest
+absolute value, often called the **dominant eigenvalue**.
+
+For any such matrix $A$, the Perron-Frobenius theorem characterizes certain
+properties of the dominant eigenvalue and its corresponding eigenvector.
+
+```{prf:Theorem} Perron-Frobenius Theorem
+:label: perron-frobenius
+
+If a matrix $A \geq 0$ then,
+
+1. the dominant eigenvalue of $A$, $r(A)$, is real-valued and nonnegative.
+2. for any other eigenvalue (possibly complex) $\lambda$ of $A$, $|\lambda| \leq r(A)$.
+3. we can find a nonnegative and nonzero eigenvector $v$ such that $Av = r(A)v$.
+
+Moreover if $A$ is also irreducible then,
+
+4. the eigenvector $v$ associated with the eigenvalue $r(A)$ is strictly positive.
+5. there exists no other positive eigenvector $v$ (except scalar multiples of $v$) associated with $r(A)$.
+
+(More of the Perron-Frobenius theorem about primitive matrices will be introduced {ref}`below `.)
+```
+
+(This is a relatively simple version of the theorem --- for more details see
+[here](https://en.wikipedia.org/wiki/Perron%E2%80%93Frobenius_theorem)).
+
+We will see applications of the theorem below.
+
+Let's build our intuition for the theorem using a simple example we have seen [before](mc_eg1).
+
+Now let's consider examples for each case.
+
+#### Example: irreducible matrix
+
+Consider the following irreducible matrix $A$:
+
+```{code-cell} ipython3
+A = np.array([[0, 1, 0],
+ [.5, 0, .5],
+ [0, 1, 0]])
+```
+
+We can compute the dominant eigenvalue and the corresponding eigenvector
+
+```{code-cell} ipython3
+eig(A)
+```
+
+Now we can see the claims of the Perron-Frobenius theorem holds for the irreducible matrix $A$:
+
+1. The dominant eigenvalue is real-valued and non-negative.
+2. All other eigenvalues have absolute values less than or equal to the dominant eigenvalue.
+3. A non-negative and nonzero eigenvector is associated with the dominant eigenvalue.
+4. As the matrix is irreducible, the eigenvector associated with the dominant eigenvalue is strictly positive.
+5. There exists no other positive eigenvector associated with the dominant eigenvalue.
+
+(prim_matrices)=
+### Primitive matrices
+
+We know that in real world situations it's hard for a matrix to be everywhere positive (although they have nice properties).
+
+The primitive matrices, however, can still give us helpful properties with looser definitions.
+
+Let $A$ be a square nonnegative matrix and let $A^k$ be the $k^{th}$ power of $A$.
+
+A matrix is called **primitive** if there exists a $k \in \mathbb{N}$ such that $A^k$ is everywhere positive.
+
+```{prf:example}
+:label: eigen2_ex_prim
+
+Recall the examples given in irreducible matrices:
+
+$$
+A = \begin{bmatrix} 0.5 & 0.1 \\
+ 0.2 & 0.2
+\end{bmatrix}
+$$
+
+$A$ here is also a primitive matrix since $A^k$ is everywhere nonnegative for $k \in \mathbb{N}$.
+
+$$
+B = \begin{bmatrix} 0 & 1 \\
+ 1 & 0
+\end{bmatrix}
+, \quad
+B^2 = \begin{bmatrix} 1 & 0 \\
+ 0 & 1
+\end{bmatrix}
+$$
+
+$B$ is irreducible but not primitive since there are always zeros in either principal diagonal or secondary diagonal.
+```
+
+We can see that if a matrix is primitive, then it implies the matrix is irreducible but not vice versa.
+
+Now let's step back to the primitive matrices part of the Perron-Frobenius theorem
+
+```{prf:Theorem} Continous of Perron-Frobenius Theorem
+:label: con-perron-frobenius
+
+If $A$ is primitive then,
+
+6. the inequality $|\lambda| \leq r(A)$ is **strict** for all eigenvalues $\lambda$ of $A$ distinct from $r(A)$, and
+7. with $v$ and $w$ normalized so that the inner product of $w$ and $v = 1$, we have
+$ r(A)^{-m} A^m$ converges to $v w^{\top}$ when $m \rightarrow \infty$. The matrix $v w^{\top}$ is called the **Perron projection** of $A$.
+```
+
+#### Example 1: primitive matrix
+
+Consider the following primitive matrix $B$:
+
+```{code-cell} ipython3
+B = np.array([[0, 1, 1],
+ [1, 0, 1],
+ [1, 1, 0]])
+
+np.linalg.matrix_power(B, 2)
+```
+
+We compute the dominant eigenvalue and the corresponding eigenvector
+
+```{code-cell} ipython3
+eig(B)
+```
+
+Now let's give some examples to see if the claims of the Perron-Frobenius theorem hold for the primitive matrix $B$:
+
+1. The dominant eigenvalue is real-valued and non-negative.
+2. All other eigenvalues have absolute values strictly less than the dominant eigenvalue.
+3. A non-negative and nonzero eigenvector is associated with the dominant eigenvalue.
+4. The eigenvector associated with the dominant eigenvalue is strictly positive.
+5. There exists no other positive eigenvector associated with the dominant eigenvalue.
+6. The inequality $|\lambda| < r(B)$ holds for all eigenvalues $\lambda$ of $B$ distinct from the dominant eigenvalue.
+
+Furthermore, we can verify the convergence property (7) of the theorem on the following examples:
+
+```{code-cell} ipython3
+def compute_perron_projection(M):
+
+ eigval, v = eig(M)
+ eigval, w = eig(M.T)
+
+ r = np.max(eigval)
+
+ # Find the index of the dominant (Perron) eigenvalue
+ i = np.argmax(eigval)
+
+ # Get the Perron eigenvectors
+ v_P = v[:, i].reshape(-1, 1)
+ w_P = w[:, i].reshape(-1, 1)
+
+ # Normalize the left and right eigenvectors
+ norm_factor = w_P.T @ v_P
+ v_norm = v_P / norm_factor
+
+ # Compute the Perron projection matrix
+ P = v_norm @ w_P.T
+ return P, r
+
+def check_convergence(M):
+ P, r = compute_perron_projection(M)
+ print("Perron projection:")
+ print(P)
+
+ # Define a list of values for n
+ n_list = [1, 10, 100, 1000, 10000]
+
+ for n in n_list:
+
+ # Compute (A/r)^n
+ M_n = np.linalg.matrix_power(M/r, n)
+
+ # Compute the difference between A^n / r^n and the Perron projection
+ diff = np.abs(M_n - P)
+
+ # Calculate the norm of the difference matrix
+ diff_norm = np.linalg.norm(diff, 'fro')
+ print(f"n = {n}, error = {diff_norm:.10f}")
+
+
+A1 = np.array([[1, 2],
+ [1, 4]])
+
+A2 = np.array([[0, 1, 1],
+ [1, 0, 1],
+ [1, 1, 0]])
+
+A3 = np.array([[0.971, 0.029, 0.1, 1],
+ [0.145, 0.778, 0.077, 0.59],
+ [0.1, 0.508, 0.492, 1.12],
+ [0.2, 0.8, 0.71, 0.95]])
+
+for M in A1, A2, A3:
+ print("Matrix:")
+ print(M)
+ check_convergence(M)
+ print()
+ print("-"*36)
+ print()
+```
+
+The convergence is not observed in cases of non-primitive matrices.
+
+Let's go through an example
+
+```{code-cell} ipython3
+B = np.array([[0, 1, 1],
+ [1, 0, 0],
+ [1, 0, 0]])
+
+# This shows that the matrix is not primitive
+print("Matrix:")
+print(B)
+print("100th power of matrix B:")
+print(np.linalg.matrix_power(B, 100))
+
+check_convergence(B)
+```
+
+The result shows that the matrix is not primitive as it is not everywhere positive.
+
+These examples show how the Perron-Frobenius theorem relates to the eigenvalues and eigenvectors of positive matrices and the convergence of the power of matrices.
+
+In fact we have already seen the theorem in action before in {ref}`the Markov chain lecture `.
+
+(spec_markov)=
+#### Example 2: connection to Markov chains
+
+We are now prepared to bridge the languages spoken in the two lectures.
+
+A primitive matrix is both irreducible and aperiodic.
+
+So Perron-Frobenius theorem explains why both {ref}`Imam and Temple matrix ` and [Hamilton matrix](https://en.wikipedia.org/wiki/Hamiltonian_matrix) converge to a stationary distribution, which is the Perron projection of the two matrices
+
+```{code-cell} ipython3
+P = np.array([[0.68, 0.12, 0.20],
+ [0.50, 0.24, 0.26],
+ [0.36, 0.18, 0.46]])
+
+print(compute_perron_projection(P)[0])
+```
+
+```{code-cell} ipython3
+mc = qe.MarkovChain(P)
+ψ_star = mc.stationary_distributions[0]
+ψ_star
+```
+
+```{code-cell} ipython3
+P_hamilton = np.array([[0.971, 0.029, 0.000],
+ [0.145, 0.778, 0.077],
+ [0.000, 0.508, 0.492]])
+
+print(compute_perron_projection(P_hamilton)[0])
+```
+
+```{code-cell} ipython3
+mc = qe.MarkovChain(P_hamilton)
+ψ_star = mc.stationary_distributions[0]
+ψ_star
+```
+
+We can also verify other properties hinted by Perron-Frobenius in these stochastic matrices.
+
++++
+
+Another example is the relationship between convergence gap and convergence rate.
+
+In the {ref}`exercise`, we stated that the convergence rate is determined by the spectral gap, the difference between the largest and the second largest eigenvalue.
+
+This can be proven using what we have learned here.
+
+Please note that we use $\mathbb{1}$ for a vector of ones in this lecture.
+
+With Markov model $M$ with state space $S$ and transition matrix $P$, we can write $P^t$ as
+
+$$
+P^t=\sum_{i=1}^{n-1} \lambda_i^t v_i w_i^{\top}+\mathbb{1} \psi^*,
+$$
+
+This is proven in {cite}`sargent2023economic` and a nice discussion can be found [here](https://math.stackexchange.com/questions/2433997/can-all-matrices-be-decomposed-as-product-of-right-and-left-eigenvector).
+
+In this formula $\lambda_i$ is an eigenvalue of $P$ with corresponding right and left eigenvectors $v_i$ and $w_i$ .
+
+Premultiplying $P^t$ by arbitrary $\psi \in \mathscr{D}(S)$ and rearranging now gives
+
+$$
+\psi P^t-\psi^*=\sum_{i=1}^{n-1} \lambda_i^t \psi v_i w_i^{\top}
+$$
+
+Recall that eigenvalues are ordered from smallest to largest from $i = 1 ... n$.
+
+As we have seen, the largest eigenvalue for a primitive stochastic matrix is one.
+
+This can be proven using [Gershgorin Circle Theorem](https://en.wikipedia.org/wiki/Gershgorin_circle_theorem),
+but it is out of the scope of this lecture.
+
+So by the statement (6) of Perron-Frobenius theorem, $\lambda_i<1$ for all $i` to find the solution $x^{*}$ if it exists.
+
+```{exercise-end}
+```
+
+```{solution-start} eig_ex1
+:class: dropdown
+```
+
+```{code-cell} ipython3
+A = np.array([[0.3, 0.2, 0.3],
+ [0.2, 0.4, 0.3],
+ [0.2, 0.5, 0.1]])
+
+evals, evecs = eig(A)
+
+r = max(abs(λ) for λ in evals) #dominant eigenvalue/spectral radius
+print(r)
+```
+
+Since we have $r(A) < 1$ we can thus find the solution using the Neumann Series Lemma.
+
+```{code-cell} ipython3
+I = np.identity(3)
+B = I - A
+
+d = np.array([4, 5, 12])
+d.shape = (3,1)
+
+B_inv = np.linalg.inv(B)
+x_star = B_inv @ d
+print(x_star)
+```
+
+```{solution-end}
+```
diff --git a/book/_build/html/_sources/equalizing_difference.ipynb b/book/_build/html/_sources/equalizing_difference.ipynb
new file mode 100644
index 0000000..b6bb479
--- /dev/null
+++ b/book/_build/html/_sources/equalizing_difference.ipynb
@@ -0,0 +1,830 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "824e704a",
+ "metadata": {},
+ "source": [
+ "# Equalizing Difference Model\n",
+ "\n",
+ "## Overview\n",
+ "\n",
+ "This lecture presents a model of the college-high-school wage gap in which the\n",
+ "\"time to build\" a college graduate plays a key role.\n",
+ "\n",
+ "\n",
+ "Milton Friedman invented the model to study whether differences in earnings of US dentists and doctors were outcomes of competitive labor markets or whether\n",
+ "they reflected entry barriers imposed by governments working in conjunction with doctors' professional organizations. \n",
+ "\n",
+ "Chapter 4 of Jennifer Burns {cite}`Burns_2023` describes Milton Friedman's joint work with Simon Kuznets that eventually led to the publication of {cite}`kuznets1939incomes` and {cite}`friedman1954incomes`.\n",
+ "\n",
+ "To map Friedman's application into our model, think of our high school students as Friedman's dentists and our college graduates as Friedman's doctors. \n",
+ "\n",
+ "\n",
+ "Our presentation is \"incomplete\" in the sense that it is based on a single equation that would be part of set equilibrium conditions of a more fully articulated model.\n",
+ "\n",
+ "This ''equalizing difference'' equation determines a college-high-school wage ratio that equalizes present values of a high school educated worker and a college educated worker.\n",
+ "\n",
+ "The idea is that lifetime earnings somehow adjust to make a new high school worker indifferent between going to college and not going to college but instead going to work immediately.\n",
+ "\n",
+ "(The job of the \"other equations\" in a more complete model would be to describe what adjusts to bring about this outcome.)\n",
+ "\n",
+ "Our model is just one example of an \"equalizing difference\" theory of relative wage rates, a class of theories dating back at least to Adam Smith's **Wealth of Nations** {cite}`smith2010wealth`. \n",
+ "\n",
+ "For most of this lecture, the only mathematical tools that we'll use are from linear algebra, in particular, matrix multiplication and matrix inversion.\n",
+ "\n",
+ "However, near the end of the lecture, we'll use calculus just in case readers want to see how computing partial derivatives could let us present some findings more concisely. \n",
+ "\n",
+ "And doing that will let illustrate how good Python is at doing calculus!\n",
+ "\n",
+ "But if you don't know calculus, our tools from linear algebra are certainly enough.\n",
+ "\n",
+ "As usual, we'll start by importing some Python modules."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8fea8ed2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "from collections import namedtuple\n",
+ "from sympy import Symbol, Lambda, symbols"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b65ab7e0",
+ "metadata": {},
+ "source": [
+ "## The indifference condition\n",
+ "\n",
+ "The key idea is that the entry level college wage premium has to adjust to make a representative worker indifferent between going to college and not going to college.\n",
+ "\n",
+ "Let\n",
+ "\n",
+ " * $R > 1$ be the gross rate of return on a one-period bond\n",
+ "\n",
+ " * $t = 0, 1, 2, \\ldots T$ denote the years that a person either works or attends college\n",
+ " \n",
+ " * $0$ denote the first period after high school that a person can work if he does not go to college\n",
+ " \n",
+ " * $T$ denote the last period that a person works\n",
+ " \n",
+ " * $w_t^h$ be the wage at time $t$ of a high school graduate\n",
+ " \n",
+ " * $w_t^c$ be the wage at time $t$ of a college graduate\n",
+ " \n",
+ " * $\\gamma_h > 1$ be the (gross) rate of growth of wages of a high school graduate, so that\n",
+ " $ w_t^h = w_0^h \\gamma_h^t$\n",
+ " \n",
+ " * $\\gamma_c > 1$ be the (gross) rate of growth of wages of a college graduate, so that\n",
+ " $ w_t^c = w_0^c \\gamma_c^t$\n",
+ "\n",
+ " * $D$ be the upfront monetary costs of going to college\n",
+ "\n",
+ "We now compute present values that a new high school graduate earns if\n",
+ "\n",
+ " * he goes to work immediately and earns wages paid to someone without a college education\n",
+ " * he goes to college for four years and after graduating earns wages paid to a college graduate\n",
+ "\n",
+ "### Present value of a high school educated worker\n",
+ "\n",
+ "If someone goes to work immediately after high school and works for the $T+1$ years $t=0, 1, 2, \\ldots, T$, she earns present value\n",
+ "\n",
+ "$$\n",
+ "h_0 = \\sum_{t=0}^T R^{-t} w_t^h = w_0^h \\left[ \\frac{1 - (R^{-1} \\gamma_h)^{T+1} }{1 - R^{-1} \\gamma_h } \\right] \\equiv w_0^h A_h \n",
+ "$$\n",
+ "\n",
+ "where \n",
+ "\n",
+ "$$\n",
+ "A_h = \\left[ \\frac{1 - (R^{-1} \\gamma_h)^{T+1} }{1 - R^{-1} \\gamma_h } \\right].\n",
+ "$$\n",
+ "\n",
+ "The present value $h_0$ is the \"human wealth\" at the beginning of time $0$ of someone who chooses not to attend college but instead to go to work immediately at the wage of a high school graduate.\n",
+ "\n",
+ "### Present value of a college-bound new high school graduate\n",
+ "\n",
+ "\n",
+ "If someone goes to college for the four years $t=0, 1, 2, 3$ during which she earns $0$, but then goes to work immediately after college and works for the $T-3$ years $t=4, 5, \\ldots ,T$, she earns present value\n",
+ "\n",
+ "$$\n",
+ "c_0 = \\sum_{t=4}^T R^{-t} w_t^c = w_0^c (R^{-1} \\gamma_c)^4 \\left[ \\frac{1 - (R^{-1} \\gamma_c)^{T-3} }{1 - R^{-1} \\gamma_c } \\right] \\equiv w_0^c A_c\n",
+ "$$\n",
+ "\n",
+ "where\n",
+ "\n",
+ "$$\n",
+ "A_c = (R^{-1} \\gamma_c)^4 \\left[ \\frac{1 - (R^{-1} \\gamma_c)^{T-3} }{1 - R^{-1} \\gamma_c } \\right] .\n",
+ "$$ \n",
+ "\n",
+ "The present value $c_0$ is the \"human wealth\" at the beginning of time $0$ of someone who chooses to attend college for four years and then start to work at time $t=4$ at the wage of a college graduate.\n",
+ "\n",
+ "\n",
+ "Assume that college tuition plus four years of room and board amount to $D$ and must be paid at time $0$.\n",
+ "\n",
+ "So net of monetary cost of college, the present value of attending college as of the first period after high school is\n",
+ "\n",
+ "$$ \n",
+ "c_0 - D\n",
+ "$$\n",
+ "\n",
+ "We now formulate a pure **equalizing difference** model of the initial college-high school wage gap $\\phi$ that verifies \n",
+ "\n",
+ "$$\n",
+ "w_0^c = \\phi w_0^h \n",
+ "$$\n",
+ "\n",
+ "We suppose that $R, \\gamma_h, \\gamma_c, T$ and also $w_0^h$ are fixed parameters. \n",
+ "\n",
+ "We start by noting that the pure equalizing difference model asserts that the college-high-school wage gap $\\phi$ solves an \n",
+ "\"equalizing\" equation that sets the present value not going to college equal to the present value of going to college:\n",
+ "\n",
+ "\n",
+ "$$\n",
+ "h_0 = c_0 - D\n",
+ "$$ \n",
+ "\n",
+ "or\n",
+ "\n",
+ "$$ \n",
+ "w_0^h A_h = \\phi w_0^h A_c - D .\n",
+ "$$ (eq:equalize)\n",
+ "\n",
+ "This \"indifference condition\" is the heart of the model.\n",
+ "\n",
+ "Solving equation {eq}`eq:equalize` for the college wage premium $\\phi$ we obtain\n",
+ "\n",
+ "$$\n",
+ "\\phi = \\frac{A_h}{A_c} + \\frac{D}{w_0^h A_c} .\n",
+ "$$ (eq:wagepremium)\n",
+ "\n",
+ "In a **free college** special case $D =0$.\n",
+ "\n",
+ "Here the only cost of going to college is the forgone earnings from being a high school educated worker. \n",
+ "\n",
+ "In that case,\n",
+ "\n",
+ "$$\n",
+ "\\phi = \\frac{A_h}{A_c} . \n",
+ "$$\n",
+ "\n",
+ "In the next section we'll write Python code to compute $\\phi$ and plot it as a function of its determinants.\n",
+ "\n",
+ "## Computations\n",
+ "\n",
+ "\n",
+ "We can have some fun with examples that tweak various parameters,\n",
+ "prominently including $\\gamma_h, \\gamma_c, R$.\n",
+ "\n",
+ "Now let's write some Python code to compute $\\phi$ and plot it as a function of some of its determinants."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9a2065e5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Define the namedtuple for the equalizing difference model\n",
+ "EqDiffModel = namedtuple('EqDiffModel', 'R T γ_h γ_c w_h0 D')\n",
+ "\n",
+ "def create_edm(R=1.05, # gross rate of return\n",
+ " T=40, # time horizon\n",
+ " γ_h=1.01, # high-school wage growth\n",
+ " γ_c=1.01, # college wage growth\n",
+ " w_h0=1, # initial wage (high school)\n",
+ " D=10, # cost for college\n",
+ " ):\n",
+ " \n",
+ " return EqDiffModel(R, T, γ_h, γ_c, w_h0, D)\n",
+ "\n",
+ "def compute_gap(model):\n",
+ " R, T, γ_h, γ_c, w_h0, D = model\n",
+ " \n",
+ " A_h = (1 - (γ_h/R)**(T+1)) / (1 - γ_h/R)\n",
+ " A_c = (1 - (γ_c/R)**(T-3)) / (1 - γ_c/R) * (γ_c/R)**4\n",
+ " ϕ = A_h / A_c + D / (w_h0 * A_c)\n",
+ " \n",
+ " return ϕ"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6489235f",
+ "metadata": {},
+ "source": [
+ "Using vectorization instead of loops,\n",
+ "we build some functions to help do comparative statics .\n",
+ "\n",
+ "For a given instance of the class, we want to recompute $\\phi$ when one parameter changes and others remain fixed.\n",
+ "\n",
+ "Let's do an example."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "97097bae",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ex1 = create_edm()\n",
+ "gap1 = compute_gap(ex1)\n",
+ "\n",
+ "gap1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b21ee803",
+ "metadata": {},
+ "source": [
+ "Let's not charge for college and recompute $\\phi$.\n",
+ "\n",
+ "The initial college wage premium should go down."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "cc006ad6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# free college\n",
+ "ex2 = create_edm(D=0)\n",
+ "gap2 = compute_gap(ex2)\n",
+ "gap2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a6eb2a63",
+ "metadata": {},
+ "source": [
+ "Let us construct some graphs that show us how the initial college-high-school wage ratio $\\phi$ would change if one of its determinants were to change. \n",
+ "\n",
+ "Let's start with the gross interest rate $R$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "be443049",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "R_arr = np.linspace(1, 1.2, 50)\n",
+ "models = [create_edm(R=r) for r in R_arr]\n",
+ "gaps = [compute_gap(model) for model in models]\n",
+ "\n",
+ "plt.plot(R_arr, gaps)\n",
+ "plt.xlabel(r'$R$')\n",
+ "plt.ylabel(r'wage gap')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4371836f",
+ "metadata": {},
+ "source": [
+ "Evidently, the initial wage ratio $\\phi$ must rise to compensate a prospective high school student for **waiting** to start receiving income -- remember that while she is earning nothing in years $t=0, 1, 2, 3$, the high school worker is earning a salary.\n",
+ "\n",
+ "Not let's study what happens to the initial wage ratio $\\phi$ if the rate of growth of college wages rises, holding constant other \n",
+ "determinants of $\\phi$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5919447d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "γc_arr = np.linspace(1, 1.2, 50)\n",
+ "models = [create_edm(γ_c=γ_c) for γ_c in γc_arr]\n",
+ "gaps = [compute_gap(model) for model in models]\n",
+ "\n",
+ "plt.plot(γc_arr, gaps)\n",
+ "plt.xlabel(r'$\\gamma_c$')\n",
+ "plt.ylabel(r'wage gap')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "60f07bf4",
+ "metadata": {},
+ "source": [
+ "Notice how the initial wage gap falls when the rate of growth $\\gamma_c$ of college wages rises. \n",
+ "\n",
+ "The wage gap falls to \"equalize\" the present values of the two types of career, one as a high school worker, the other as a college worker.\n",
+ "\n",
+ "Can you guess what happens to the initial wage ratio $\\phi$ when next we vary the rate of growth of high school wages, holding all other determinants of $\\phi$ constant? \n",
+ "\n",
+ "The following graph shows what happens."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f07f9f61",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "γh_arr = np.linspace(1, 1.1, 50)\n",
+ "models = [create_edm(γ_h=γ_h) for γ_h in γh_arr]\n",
+ "gaps = [compute_gap(model) for model in models]\n",
+ "\n",
+ "plt.plot(γh_arr, gaps)\n",
+ "plt.xlabel(r'$\\gamma_h$')\n",
+ "plt.ylabel(r'wage gap')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1652c808",
+ "metadata": {},
+ "source": [
+ "## Entrepreneur-worker interpretation\n",
+ "\n",
+ "We can add a parameter and reinterpret variables to get a model of entrepreneurs versus workers.\n",
+ "\n",
+ "We now let $h$ be the present value of a \"worker\".\n",
+ "\n",
+ "We define the present value of an entrepreneur to be\n",
+ "\n",
+ "$$\n",
+ "c_0 = \\pi \\sum_{t=4}^T R^{-t} w_t^c\n",
+ "$$\n",
+ "\n",
+ "where $\\pi \\in (0,1) $ is the probability that an entrepreneur's \"project\" succeeds.\n",
+ "\n",
+ "For our model of workers and firms, we'll interpret $D$ as the cost of becoming an entrepreneur. \n",
+ "\n",
+ "This cost might include costs of hiring workers, office space, and lawyers. \n",
+ "\n",
+ "What we used to call the college, high school wage gap $\\phi$ now becomes the ratio\n",
+ "of a successful entrepreneur's earnings to a worker's earnings. \n",
+ "\n",
+ "We'll find that as $\\pi$ decreases, $\\phi$ increases, indicating that the riskier it is to\n",
+ "be an entrepreneur, the higher must be the reward for a successful project. \n",
+ "\n",
+ "Now let's adopt the entrepreneur-worker interpretation of our model"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7f403910",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Define a model of entrepreneur-worker interpretation\n",
+ "EqDiffModel = namedtuple('EqDiffModel', 'R T γ_h γ_c w_h0 D π')\n",
+ "\n",
+ "def create_edm_π(R=1.05, # gross rate of return\n",
+ " T=40, # time horizon\n",
+ " γ_h=1.01, # high-school wage growth\n",
+ " γ_c=1.01, # college wage growth\n",
+ " w_h0=1, # initial wage (high school)\n",
+ " D=10, # cost for college\n",
+ " π=0 # chance of business success\n",
+ " ):\n",
+ " \n",
+ " return EqDiffModel(R, T, γ_h, γ_c, w_h0, D, π)\n",
+ "\n",
+ "\n",
+ "def compute_gap(model):\n",
+ " R, T, γ_h, γ_c, w_h0, D, π = model\n",
+ " \n",
+ " A_h = (1 - (γ_h/R)**(T+1)) / (1 - γ_h/R)\n",
+ " A_c = (1 - (γ_c/R)**(T-3)) / (1 - γ_c/R) * (γ_c/R)**4\n",
+ " \n",
+ " # Incorprate chance of success\n",
+ " A_c = π * A_c\n",
+ " \n",
+ " ϕ = A_h / A_c + D / (w_h0 * A_c)\n",
+ " return ϕ"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "276b9594",
+ "metadata": {},
+ "source": [
+ "If the probability that a new business succeeds is $0.2$, let's compute the initial wage premium for successful entrepreneurs."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c1bd81e1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ex3 = create_edm_π(π=0.2)\n",
+ "gap3 = compute_gap(ex3)\n",
+ "\n",
+ "gap3"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0630d0cd",
+ "metadata": {},
+ "source": [
+ "Now let's study how the initial wage premium for successful entrepreneurs depend on the success probability."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5556bf89",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "π_arr = np.linspace(0.2, 1, 50)\n",
+ "models = [create_edm_π(π=π) for π in π_arr]\n",
+ "gaps = [compute_gap(model) for model in models]\n",
+ "\n",
+ "plt.plot(π_arr, gaps)\n",
+ "plt.ylabel(r'wage gap')\n",
+ "plt.xlabel(r'$\\pi$')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "df3b826c",
+ "metadata": {},
+ "source": [
+ "Does the graph make sense to you?\n",
+ "\n",
+ "\n",
+ "\n",
+ "## An application of calculus\n",
+ "\n",
+ "So far, we have used only linear algebra and it has been a good enough tool for us to figure out how our model works.\n",
+ "\n",
+ "However, someone who knows calculus might want us just to take partial derivatives.\n",
+ "\n",
+ "We'll do that now.\n",
+ "\n",
+ "A reader who doesn't know calculus could read no further and feel confident that applying linear algebra has taught us the main properties of the model.\n",
+ "\n",
+ "But for a reader interested in how we can get Python to do all the hard work involved in computing partial derivatives, we'll say a few things about that now. \n",
+ "\n",
+ "We'll use the Python module 'sympy' to compute partial derivatives of $\\phi$ with respect to the parameters that determine it.\n",
+ "\n",
+ "Define symbols"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "41cd9aba",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "γ_h, γ_c, w_h0, D = symbols('\\gamma_h, \\gamma_c, w_0^h, D', real=True)\n",
+ "R, T = Symbol('R', real=True), Symbol('T', integer=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "77340f46",
+ "metadata": {},
+ "source": [
+ "Define function $A_h$"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "237fee51",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "A_h = Lambda((γ_h, R, T), (1 - (γ_h/R)**(T+1)) / (1 - γ_h/R))\n",
+ "A_h"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ee96b107",
+ "metadata": {},
+ "source": [
+ "Define function $A_c$"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bb20ac3c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "A_c = Lambda((γ_c, R, T), (1 - (γ_c/R)**(T-3)) / (1 - γ_c/R) * (γ_c/R)**4)\n",
+ "A_c"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9c3504e9",
+ "metadata": {},
+ "source": [
+ "Now, define $\\phi$"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f98bb420",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ϕ = Lambda((D, γ_h, γ_c, R, T, w_h0), A_h(γ_h, R, T)/A_c(γ_c, R, T) + D/(w_h0*A_c(γ_c, R, T)))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4c9e7af1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ϕ"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f3319e10",
+ "metadata": {},
+ "source": [
+ "We begin by setting default parameter values."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "fc0f873e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "R_value = 1.05\n",
+ "T_value = 40\n",
+ "γ_h_value, γ_c_value = 1.01, 1.01\n",
+ "w_h0_value = 1\n",
+ "D_value = 10"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d6ab1db2",
+ "metadata": {},
+ "source": [
+ "Now let's compute $\\frac{\\partial \\phi}{\\partial D}$ and then evaluate it at the default values"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7488e8a0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ϕ_D = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(D)\n",
+ "ϕ_D"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "69fc651f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Numerical value at default parameters\n",
+ "ϕ_D_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_D)\n",
+ "ϕ_D_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d2cf56f1",
+ "metadata": {},
+ "source": [
+ "Thus, as with our earlier graph, we find that raising $R$ increases the initial college wage premium $\\phi$.\n",
+ "\n",
+ "Compute $\\frac{\\partial \\phi}{\\partial T}$ and evaluate it at default parameters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d45623b4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ϕ_T = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(T)\n",
+ "ϕ_T"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "23d70d6a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Numerical value at default parameters\n",
+ "ϕ_T_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_T)\n",
+ "ϕ_T_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e8f6d2dc",
+ "metadata": {},
+ "source": [
+ "We find that raising $T$ decreases the initial college wage premium $\\phi$. \n",
+ "\n",
+ "This is because college graduates now have longer career lengths to \"pay off\" the time and other costs they paid to go to college\n",
+ "\n",
+ "Let's compute $\\frac{\\partial \\phi}{\\partial γ_h}$ and evaluate it at default parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6b234daa",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ϕ_γ_h = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(γ_h)\n",
+ "ϕ_γ_h"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ac8401bf",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Numerical value at default parameters\n",
+ "ϕ_γ_h_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_γ_h)\n",
+ "ϕ_γ_h_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "fb4f99c8",
+ "metadata": {},
+ "source": [
+ "We find that raising $\\gamma_h$ increases the initial college wage premium $\\phi$, in line with our earlier graphical analysis.\n",
+ "\n",
+ "Compute $\\frac{\\partial \\phi}{\\partial γ_c}$ and evaluate it numerically at default parameter values"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3af4a76e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ϕ_γ_c = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(γ_c)\n",
+ "ϕ_γ_c"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "dfe9afbc",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Numerical value at default parameters\n",
+ "ϕ_γ_c_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_γ_c)\n",
+ "ϕ_γ_c_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a5c43b2d",
+ "metadata": {},
+ "source": [
+ "We find that raising $\\gamma_c$ decreases the initial college wage premium $\\phi$, in line with our earlier graphical analysis.\n",
+ "\n",
+ "Let's compute $\\frac{\\partial \\phi}{\\partial R}$ and evaluate it numerically at default parameter values"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b5d35e7c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ϕ_R = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(R)\n",
+ "ϕ_R"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "84ea1fcd",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Numerical value at default parameters\n",
+ "ϕ_R_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_R)\n",
+ "ϕ_R_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "52f87e22",
+ "metadata": {},
+ "source": [
+ "We find that raising the gross interest rate $R$ increases the initial college wage premium $\\phi$, in line with our earlier graphical analysis."
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.16.1"
+ }
+ },
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "source_map": [
+ 12,
+ 50,
+ 55,
+ 180,
+ 202,
+ 211,
+ 216,
+ 222,
+ 227,
+ 233,
+ 242,
+ 249,
+ 258,
+ 268,
+ 277,
+ 305,
+ 332,
+ 336,
+ 341,
+ 345,
+ 354,
+ 376,
+ 379,
+ 383,
+ 386,
+ 390,
+ 393,
+ 397,
+ 401,
+ 403,
+ 407,
+ 413,
+ 417,
+ 422,
+ 426,
+ 432,
+ 437,
+ 441,
+ 449,
+ 454,
+ 458,
+ 464,
+ 469,
+ 473,
+ 479,
+ 484,
+ 488
+ ]
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/equalizing_difference.md b/book/_build/html/_sources/equalizing_difference.md
new file mode 100644
index 0000000..c65bbf9
--- /dev/null
+++ b/book/_build/html/_sources/equalizing_difference.md
@@ -0,0 +1,490 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.16.1
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+# Equalizing Difference Model
+
+## Overview
+
+This lecture presents a model of the college-high-school wage gap in which the
+"time to build" a college graduate plays a key role.
+
+
+Milton Friedman invented the model to study whether differences in earnings of US dentists and doctors were outcomes of competitive labor markets or whether
+they reflected entry barriers imposed by governments working in conjunction with doctors' professional organizations.
+
+Chapter 4 of Jennifer Burns {cite}`Burns_2023` describes Milton Friedman's joint work with Simon Kuznets that eventually led to the publication of {cite}`kuznets1939incomes` and {cite}`friedman1954incomes`.
+
+To map Friedman's application into our model, think of our high school students as Friedman's dentists and our college graduates as Friedman's doctors.
+
+
+Our presentation is "incomplete" in the sense that it is based on a single equation that would be part of set equilibrium conditions of a more fully articulated model.
+
+This ''equalizing difference'' equation determines a college-high-school wage ratio that equalizes present values of a high school educated worker and a college educated worker.
+
+The idea is that lifetime earnings somehow adjust to make a new high school worker indifferent between going to college and not going to college but instead going to work immediately.
+
+(The job of the "other equations" in a more complete model would be to describe what adjusts to bring about this outcome.)
+
+Our model is just one example of an "equalizing difference" theory of relative wage rates, a class of theories dating back at least to Adam Smith's **Wealth of Nations** {cite}`smith2010wealth`.
+
+For most of this lecture, the only mathematical tools that we'll use are from linear algebra, in particular, matrix multiplication and matrix inversion.
+
+However, near the end of the lecture, we'll use calculus just in case readers want to see how computing partial derivatives could let us present some findings more concisely.
+
+And doing that will let illustrate how good Python is at doing calculus!
+
+But if you don't know calculus, our tools from linear algebra are certainly enough.
+
+As usual, we'll start by importing some Python modules.
+
+```{code-cell} ipython3
+import numpy as np
+import matplotlib.pyplot as plt
+from collections import namedtuple
+from sympy import Symbol, Lambda, symbols
+```
+
+## The indifference condition
+
+The key idea is that the entry level college wage premium has to adjust to make a representative worker indifferent between going to college and not going to college.
+
+Let
+
+ * $R > 1$ be the gross rate of return on a one-period bond
+
+ * $t = 0, 1, 2, \ldots T$ denote the years that a person either works or attends college
+
+ * $0$ denote the first period after high school that a person can work if he does not go to college
+
+ * $T$ denote the last period that a person works
+
+ * $w_t^h$ be the wage at time $t$ of a high school graduate
+
+ * $w_t^c$ be the wage at time $t$ of a college graduate
+
+ * $\gamma_h > 1$ be the (gross) rate of growth of wages of a high school graduate, so that
+ $ w_t^h = w_0^h \gamma_h^t$
+
+ * $\gamma_c > 1$ be the (gross) rate of growth of wages of a college graduate, so that
+ $ w_t^c = w_0^c \gamma_c^t$
+
+ * $D$ be the upfront monetary costs of going to college
+
+We now compute present values that a new high school graduate earns if
+
+ * he goes to work immediately and earns wages paid to someone without a college education
+ * he goes to college for four years and after graduating earns wages paid to a college graduate
+
+### Present value of a high school educated worker
+
+If someone goes to work immediately after high school and works for the $T+1$ years $t=0, 1, 2, \ldots, T$, she earns present value
+
+$$
+h_0 = \sum_{t=0}^T R^{-t} w_t^h = w_0^h \left[ \frac{1 - (R^{-1} \gamma_h)^{T+1} }{1 - R^{-1} \gamma_h } \right] \equiv w_0^h A_h
+$$
+
+where
+
+$$
+A_h = \left[ \frac{1 - (R^{-1} \gamma_h)^{T+1} }{1 - R^{-1} \gamma_h } \right].
+$$
+
+The present value $h_0$ is the "human wealth" at the beginning of time $0$ of someone who chooses not to attend college but instead to go to work immediately at the wage of a high school graduate.
+
+### Present value of a college-bound new high school graduate
+
+
+If someone goes to college for the four years $t=0, 1, 2, 3$ during which she earns $0$, but then goes to work immediately after college and works for the $T-3$ years $t=4, 5, \ldots ,T$, she earns present value
+
+$$
+c_0 = \sum_{t=4}^T R^{-t} w_t^c = w_0^c (R^{-1} \gamma_c)^4 \left[ \frac{1 - (R^{-1} \gamma_c)^{T-3} }{1 - R^{-1} \gamma_c } \right] \equiv w_0^c A_c
+$$
+
+where
+
+$$
+A_c = (R^{-1} \gamma_c)^4 \left[ \frac{1 - (R^{-1} \gamma_c)^{T-3} }{1 - R^{-1} \gamma_c } \right] .
+$$
+
+The present value $c_0$ is the "human wealth" at the beginning of time $0$ of someone who chooses to attend college for four years and then start to work at time $t=4$ at the wage of a college graduate.
+
+
+Assume that college tuition plus four years of room and board amount to $D$ and must be paid at time $0$.
+
+So net of monetary cost of college, the present value of attending college as of the first period after high school is
+
+$$
+c_0 - D
+$$
+
+We now formulate a pure **equalizing difference** model of the initial college-high school wage gap $\phi$ that verifies
+
+$$
+w_0^c = \phi w_0^h
+$$
+
+We suppose that $R, \gamma_h, \gamma_c, T$ and also $w_0^h$ are fixed parameters.
+
+We start by noting that the pure equalizing difference model asserts that the college-high-school wage gap $\phi$ solves an
+"equalizing" equation that sets the present value not going to college equal to the present value of going to college:
+
+
+$$
+h_0 = c_0 - D
+$$
+
+or
+
+$$
+w_0^h A_h = \phi w_0^h A_c - D .
+$$ (eq:equalize)
+
+This "indifference condition" is the heart of the model.
+
+Solving equation {eq}`eq:equalize` for the college wage premium $\phi$ we obtain
+
+$$
+\phi = \frac{A_h}{A_c} + \frac{D}{w_0^h A_c} .
+$$ (eq:wagepremium)
+
+In a **free college** special case $D =0$.
+
+Here the only cost of going to college is the forgone earnings from being a high school educated worker.
+
+In that case,
+
+$$
+\phi = \frac{A_h}{A_c} .
+$$
+
+In the next section we'll write Python code to compute $\phi$ and plot it as a function of its determinants.
+
+## Computations
+
+
+We can have some fun with examples that tweak various parameters,
+prominently including $\gamma_h, \gamma_c, R$.
+
+Now let's write some Python code to compute $\phi$ and plot it as a function of some of its determinants.
+
+```{code-cell} ipython3
+# Define the namedtuple for the equalizing difference model
+EqDiffModel = namedtuple('EqDiffModel', 'R T γ_h γ_c w_h0 D')
+
+def create_edm(R=1.05, # gross rate of return
+ T=40, # time horizon
+ γ_h=1.01, # high-school wage growth
+ γ_c=1.01, # college wage growth
+ w_h0=1, # initial wage (high school)
+ D=10, # cost for college
+ ):
+
+ return EqDiffModel(R, T, γ_h, γ_c, w_h0, D)
+
+def compute_gap(model):
+ R, T, γ_h, γ_c, w_h0, D = model
+
+ A_h = (1 - (γ_h/R)**(T+1)) / (1 - γ_h/R)
+ A_c = (1 - (γ_c/R)**(T-3)) / (1 - γ_c/R) * (γ_c/R)**4
+ ϕ = A_h / A_c + D / (w_h0 * A_c)
+
+ return ϕ
+```
+
+Using vectorization instead of loops,
+we build some functions to help do comparative statics .
+
+For a given instance of the class, we want to recompute $\phi$ when one parameter changes and others remain fixed.
+
+Let's do an example.
+
+```{code-cell} ipython3
+ex1 = create_edm()
+gap1 = compute_gap(ex1)
+
+gap1
+```
+
+Let's not charge for college and recompute $\phi$.
+
+The initial college wage premium should go down.
+
+```{code-cell} ipython3
+# free college
+ex2 = create_edm(D=0)
+gap2 = compute_gap(ex2)
+gap2
+```
+
+Let us construct some graphs that show us how the initial college-high-school wage ratio $\phi$ would change if one of its determinants were to change.
+
+Let's start with the gross interest rate $R$.
+
+```{code-cell} ipython3
+R_arr = np.linspace(1, 1.2, 50)
+models = [create_edm(R=r) for r in R_arr]
+gaps = [compute_gap(model) for model in models]
+
+plt.plot(R_arr, gaps)
+plt.xlabel(r'$R$')
+plt.ylabel(r'wage gap')
+plt.show()
+```
+
+Evidently, the initial wage ratio $\phi$ must rise to compensate a prospective high school student for **waiting** to start receiving income -- remember that while she is earning nothing in years $t=0, 1, 2, 3$, the high school worker is earning a salary.
+
+Not let's study what happens to the initial wage ratio $\phi$ if the rate of growth of college wages rises, holding constant other
+determinants of $\phi$.
+
+```{code-cell} ipython3
+γc_arr = np.linspace(1, 1.2, 50)
+models = [create_edm(γ_c=γ_c) for γ_c in γc_arr]
+gaps = [compute_gap(model) for model in models]
+
+plt.plot(γc_arr, gaps)
+plt.xlabel(r'$\gamma_c$')
+plt.ylabel(r'wage gap')
+plt.show()
+```
+
+Notice how the initial wage gap falls when the rate of growth $\gamma_c$ of college wages rises.
+
+The wage gap falls to "equalize" the present values of the two types of career, one as a high school worker, the other as a college worker.
+
+Can you guess what happens to the initial wage ratio $\phi$ when next we vary the rate of growth of high school wages, holding all other determinants of $\phi$ constant?
+
+The following graph shows what happens.
+
+```{code-cell} ipython3
+γh_arr = np.linspace(1, 1.1, 50)
+models = [create_edm(γ_h=γ_h) for γ_h in γh_arr]
+gaps = [compute_gap(model) for model in models]
+
+plt.plot(γh_arr, gaps)
+plt.xlabel(r'$\gamma_h$')
+plt.ylabel(r'wage gap')
+plt.show()
+```
+
+## Entrepreneur-worker interpretation
+
+We can add a parameter and reinterpret variables to get a model of entrepreneurs versus workers.
+
+We now let $h$ be the present value of a "worker".
+
+We define the present value of an entrepreneur to be
+
+$$
+c_0 = \pi \sum_{t=4}^T R^{-t} w_t^c
+$$
+
+where $\pi \in (0,1) $ is the probability that an entrepreneur's "project" succeeds.
+
+For our model of workers and firms, we'll interpret $D$ as the cost of becoming an entrepreneur.
+
+This cost might include costs of hiring workers, office space, and lawyers.
+
+What we used to call the college, high school wage gap $\phi$ now becomes the ratio
+of a successful entrepreneur's earnings to a worker's earnings.
+
+We'll find that as $\pi$ decreases, $\phi$ increases, indicating that the riskier it is to
+be an entrepreneur, the higher must be the reward for a successful project.
+
+Now let's adopt the entrepreneur-worker interpretation of our model
+
+```{code-cell} ipython3
+# Define a model of entrepreneur-worker interpretation
+EqDiffModel = namedtuple('EqDiffModel', 'R T γ_h γ_c w_h0 D π')
+
+def create_edm_π(R=1.05, # gross rate of return
+ T=40, # time horizon
+ γ_h=1.01, # high-school wage growth
+ γ_c=1.01, # college wage growth
+ w_h0=1, # initial wage (high school)
+ D=10, # cost for college
+ π=0 # chance of business success
+ ):
+
+ return EqDiffModel(R, T, γ_h, γ_c, w_h0, D, π)
+
+
+def compute_gap(model):
+ R, T, γ_h, γ_c, w_h0, D, π = model
+
+ A_h = (1 - (γ_h/R)**(T+1)) / (1 - γ_h/R)
+ A_c = (1 - (γ_c/R)**(T-3)) / (1 - γ_c/R) * (γ_c/R)**4
+
+ # Incorprate chance of success
+ A_c = π * A_c
+
+ ϕ = A_h / A_c + D / (w_h0 * A_c)
+ return ϕ
+```
+
+If the probability that a new business succeeds is $0.2$, let's compute the initial wage premium for successful entrepreneurs.
+
+```{code-cell} ipython3
+ex3 = create_edm_π(π=0.2)
+gap3 = compute_gap(ex3)
+
+gap3
+```
+
+Now let's study how the initial wage premium for successful entrepreneurs depend on the success probability.
+
+```{code-cell} ipython3
+π_arr = np.linspace(0.2, 1, 50)
+models = [create_edm_π(π=π) for π in π_arr]
+gaps = [compute_gap(model) for model in models]
+
+plt.plot(π_arr, gaps)
+plt.ylabel(r'wage gap')
+plt.xlabel(r'$\pi$')
+plt.show()
+```
+
+Does the graph make sense to you?
+
+
+
+## An application of calculus
+
+So far, we have used only linear algebra and it has been a good enough tool for us to figure out how our model works.
+
+However, someone who knows calculus might want us just to take partial derivatives.
+
+We'll do that now.
+
+A reader who doesn't know calculus could read no further and feel confident that applying linear algebra has taught us the main properties of the model.
+
+But for a reader interested in how we can get Python to do all the hard work involved in computing partial derivatives, we'll say a few things about that now.
+
+We'll use the Python module 'sympy' to compute partial derivatives of $\phi$ with respect to the parameters that determine it.
+
+Define symbols
+
+```{code-cell} ipython3
+γ_h, γ_c, w_h0, D = symbols('\gamma_h, \gamma_c, w_0^h, D', real=True)
+R, T = Symbol('R', real=True), Symbol('T', integer=True)
+```
+
+Define function $A_h$
+
+```{code-cell} ipython3
+A_h = Lambda((γ_h, R, T), (1 - (γ_h/R)**(T+1)) / (1 - γ_h/R))
+A_h
+```
+
+Define function $A_c$
+
+```{code-cell} ipython3
+A_c = Lambda((γ_c, R, T), (1 - (γ_c/R)**(T-3)) / (1 - γ_c/R) * (γ_c/R)**4)
+A_c
+```
+
+Now, define $\phi$
+
+```{code-cell} ipython3
+ϕ = Lambda((D, γ_h, γ_c, R, T, w_h0), A_h(γ_h, R, T)/A_c(γ_c, R, T) + D/(w_h0*A_c(γ_c, R, T)))
+```
+
+```{code-cell} ipython3
+ϕ
+```
+
+We begin by setting default parameter values.
+
+```{code-cell} ipython3
+R_value = 1.05
+T_value = 40
+γ_h_value, γ_c_value = 1.01, 1.01
+w_h0_value = 1
+D_value = 10
+```
+
+Now let's compute $\frac{\partial \phi}{\partial D}$ and then evaluate it at the default values
+
+```{code-cell} ipython3
+ϕ_D = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(D)
+ϕ_D
+```
+
+```{code-cell} ipython3
+# Numerical value at default parameters
+ϕ_D_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_D)
+ϕ_D_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value)
+```
+
+Thus, as with our earlier graph, we find that raising $R$ increases the initial college wage premium $\phi$.
+
+Compute $\frac{\partial \phi}{\partial T}$ and evaluate it at default parameters
+
+```{code-cell} ipython3
+ϕ_T = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(T)
+ϕ_T
+```
+
+```{code-cell} ipython3
+# Numerical value at default parameters
+ϕ_T_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_T)
+ϕ_T_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value)
+```
+
+We find that raising $T$ decreases the initial college wage premium $\phi$.
+
+This is because college graduates now have longer career lengths to "pay off" the time and other costs they paid to go to college
+
+Let's compute $\frac{\partial \phi}{\partial γ_h}$ and evaluate it at default parameters.
+
+```{code-cell} ipython3
+ϕ_γ_h = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(γ_h)
+ϕ_γ_h
+```
+
+```{code-cell} ipython3
+# Numerical value at default parameters
+ϕ_γ_h_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_γ_h)
+ϕ_γ_h_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value)
+```
+
+We find that raising $\gamma_h$ increases the initial college wage premium $\phi$, in line with our earlier graphical analysis.
+
+Compute $\frac{\partial \phi}{\partial γ_c}$ and evaluate it numerically at default parameter values
+
+```{code-cell} ipython3
+ϕ_γ_c = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(γ_c)
+ϕ_γ_c
+```
+
+```{code-cell} ipython3
+# Numerical value at default parameters
+ϕ_γ_c_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_γ_c)
+ϕ_γ_c_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value)
+```
+
+We find that raising $\gamma_c$ decreases the initial college wage premium $\phi$, in line with our earlier graphical analysis.
+
+Let's compute $\frac{\partial \phi}{\partial R}$ and evaluate it numerically at default parameter values
+
+```{code-cell} ipython3
+ϕ_R = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(R)
+ϕ_R
+```
+
+```{code-cell} ipython3
+# Numerical value at default parameters
+ϕ_R_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_R)
+ϕ_R_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value)
+```
+
+We find that raising the gross interest rate $R$ increases the initial college wage premium $\phi$, in line with our earlier graphical analysis.
diff --git a/book/_build/html/_sources/french_rev.ipynb b/book/_build/html/_sources/french_rev.ipynb
new file mode 100644
index 0000000..dca0bb6
--- /dev/null
+++ b/book/_build/html/_sources/french_rev.ipynb
@@ -0,0 +1,1282 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "a30afd14",
+ "metadata": {},
+ "source": [
+ "# Inflation During French Revolution \n",
+ "\n",
+ "\n",
+ "## Overview \n",
+ "\n",
+ "This lecture describes some of the monetary and fiscal features of the French Revolution (1789-1799) described by {cite}`sargent_velde1995`.\n",
+ "\n",
+ "To finance public expenditures and service its debts, \n",
+ "the French government embarked on policy experiments.\n",
+ "\n",
+ "The authors of these experiments had in mind theories about how government monetary and fiscal policies affected economic outcomes.\n",
+ "\n",
+ "Some of those theories about monetary and fiscal policies still interest us today.\n",
+ "\n",
+ "* a **tax-smoothing** model like Robert Barro's {cite}`Barro1979`\n",
+ "\n",
+ " * this normative (i.e., prescriptive model) advises a government to finance temporary war-time surges in expenditures mostly by issuing government debt, raising taxes by just enough to service the additional debt issued during the wary; then, after the war, to roll over whatever debt the government had accumulated during the war; and to increase taxes after the war permanently by just enough to finance interest payments on that post-war government debt\n",
+ "\n",
+ "* **unpleasant monetarist arithmetic** like that described in this quanteon lecture {doc}`unpleasant`\n",
+ " \n",
+ " * mathematics involving compound interest governed French government debt dynamics in the decades preceding 1789; according to leading historians, that arithmetic set the stage for the French Revolution \n",
+ "\n",
+ "* a *real bills* theory of the effects of government open market operations in which the government *backs* new issues of paper money with government holdings of valuable real property or financial assets that holders of money can purchase from the government in exchange for their money.\n",
+ "\n",
+ " * The Revolutionaries learned about this theory from Adam Smith's 1776 book The Wealth of Nations\n",
+ " {cite}`smith2010wealth` and other contemporary sources\n",
+ "\n",
+ " * It shaped how the Revolutionaries issued a paper money called **assignats** from 1789 to 1791 \n",
+ "\n",
+ "* a classical **gold** or **silver standard**\n",
+ " \n",
+ " * Napoleon Bonaparte became head of the French government in 1799. He used this theory to guide his monetary and fiscal policies\n",
+ "\n",
+ "* a classical **inflation-tax** theory of inflation in which Philip Cagan's ({cite}`Cagan`) demand for money studied in this lecture {doc}`cagan_ree` is a key component\n",
+ "\n",
+ " * This theory helps explain French price level and money supply data from 1794 to 1797 \n",
+ "\n",
+ "* a **legal restrictions** or **financial repression** theory of the demand for real balances \n",
+ " \n",
+ " * The Twelve Members comprising the Committee of Public Safety who adminstered the Terror from June 1793 to July 1794 used this theory to shape their monetary policy \n",
+ "\n",
+ "We use matplotlib to replicate several of the graphs with which {cite}`sargent_velde1995` portrayed outcomes of these experiments \n",
+ "\n",
+ "## Data Sources\n",
+ "\n",
+ "This lecture uses data from three spreadsheets assembled by {cite}`sargent_velde1995`:\n",
+ " * [datasets/fig_3.xlsx](https://github.com/QuantEcon/lecture-python-intro/blob/main/lectures/datasets/fig_3.xlsx)\n",
+ " * [datasets/dette.xlsx](https://github.com/QuantEcon/lecture-python-intro/blob/main/lectures/datasets/dette.xlsx)\n",
+ " * [datasets/assignat.xlsx](https://github.com/QuantEcon/lecture-python-intro/blob/main/lectures/datasets/assignat.xlsx)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "384e63b5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.rcParams.update({'font.size': 12})\n",
+ "\n",
+ "base_url = 'https://github.com/QuantEcon/lecture-python-intro/raw/'\\\n",
+ " + 'main/lectures/datasets/'\n",
+ "\n",
+ "fig_3_url = f'{base_url}fig_3.xlsx'\n",
+ "dette_url = f'{base_url}dette.xlsx'\n",
+ "assignat_url = f'{base_url}assignat.xlsx'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9e71678d",
+ "metadata": {},
+ "source": [
+ "## Government Expenditures and Taxes Collected\n",
+ "\n",
+ "\n",
+ "\n",
+ "We'll start by using `matplotlib` to construct several graphs that will provide important historical context.\n",
+ "\n",
+ "These graphs are versions of ones that appear in {cite}`sargent_velde1995`.\n",
+ "\n",
+ "These graphs show that during the 18th century\n",
+ "\n",
+ " * government expenditures in France and Great Britain both surged during four big wars, and by comparable amounts\n",
+ " * In Britain, tax revenues were approximately equal to government expenditures during peace times,\n",
+ " but were substantially less than government expenditures during wars\n",
+ " * In France, even in peace time, tax revenues were substantially less than government expenditures"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7b8d7640",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Military Spending in Britain and France",
+ "name": "fr_fig4"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Read the data from Excel file\n",
+ "data2 = pd.read_excel(dette_url, \n",
+ " sheet_name='Militspe', usecols='M:X', \n",
+ " skiprows=7, nrows=102, header=None)\n",
+ "\n",
+ "# French military spending, 1685-1789, in 1726 livres\n",
+ "data4 = pd.read_excel(dette_url, \n",
+ " sheet_name='Militspe', usecols='D', \n",
+ " skiprows=3, nrows=105, header=None).squeeze()\n",
+ " \n",
+ "years = range(1685, 1790)\n",
+ "\n",
+ "plt.figure()\n",
+ "plt.plot(years, data4, '*-', linewidth=0.8)\n",
+ "\n",
+ "plt.plot(range(1689, 1791), data2.iloc[:, 4], linewidth=0.8)\n",
+ "\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "plt.gca().tick_params(labelsize=12)\n",
+ "plt.xlim([1689, 1790])\n",
+ "plt.xlabel('*: France')\n",
+ "plt.ylabel('Millions of livres')\n",
+ "plt.ylim([0, 475])\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e1dda9e5",
+ "metadata": {},
+ "source": [
+ "During the 18th century, Britain and France fought four large wars.\n",
+ "\n",
+ "Britain won the first three wars and lost the fourth.\n",
+ "\n",
+ "Each of those wars produced surges in both countries' government expenditures that each country somehow had to finance.\n",
+ "\n",
+ "Figure {numref}`fr_fig4` shows surges in military expenditures in France (in blue) and Great Britain.\n",
+ "during those four wars. \n",
+ "\n",
+ "A remarkable aspect of figure {numref}`fr_fig4` is that despite having a population less than half of France's, Britain was able to finance military expenses of about the same amounts as France's.\n",
+ "\n",
+ "This testifies to Britain's having created state institutions that could sustain high tax collections, government spending , and government borrowing. See {cite}`north1989`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "128cdc35",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Government Expenditures and Tax Revenues in Britain",
+ "name": "fr_fig2"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Read the data from Excel file\n",
+ "data2 = pd.read_excel(dette_url, sheet_name='Militspe', usecols='M:X', \n",
+ " skiprows=7, nrows=102, header=None)\n",
+ "\n",
+ "# Plot the data\n",
+ "plt.figure()\n",
+ "plt.plot(range(1689, 1791), data2.iloc[:, 5], linewidth=0.8)\n",
+ "plt.plot(range(1689, 1791), data2.iloc[:, 11], linewidth=0.8, color='red')\n",
+ "plt.plot(range(1689, 1791), data2.iloc[:, 9], linewidth=0.8, color='orange')\n",
+ "plt.plot(range(1689, 1791), data2.iloc[:, 8], 'o-', \n",
+ " markerfacecolor='none', linewidth=0.8, color='purple')\n",
+ "\n",
+ "# Customize the plot\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "plt.gca().tick_params(labelsize=12)\n",
+ "plt.xlim([1689, 1790])\n",
+ "plt.ylabel('millions of pounds', fontsize=12)\n",
+ "\n",
+ "# Add text annotations\n",
+ "plt.text(1765, 1.5, 'civil', fontsize=10)\n",
+ "plt.text(1760, 4.2, 'civil plus debt service', fontsize=10)\n",
+ "plt.text(1708, 15.5, 'total govt spending', fontsize=10)\n",
+ "plt.text(1759, 7.3, 'revenues', fontsize=10)\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "71bbd6db",
+ "metadata": {},
+ "source": [
+ "Figures {numref}`fr_fig2` and {numref}`fr_fig3` summarize British and French government fiscal policies during the century before the start of the French Revolution in 1789.\n",
+ "\n",
+ "\n",
+ "Before 1789, progressive forces in France admired how Britain had financed its government expenditures and wanted to redesign French fiscal arrangements to make them more like Britain's.\n",
+ "\n",
+ "Figure {numref}`fr_fig2` shows government expenditures and how it was distributed among expenditures for \n",
+ "\n",
+ " * civil (non-military) activities\n",
+ " * debt service, i.e., interest payments \n",
+ " * military expenditures (the yellow line minus the red line) \n",
+ "\n",
+ "Figure {numref}`fr_fig2` also plots total government revenues from tax collections (the purple circled line)\n",
+ "\n",
+ "Notice the surges in total government expenditures associated with surges in military expenditures\n",
+ "in these four wars\n",
+ "\n",
+ " * Wars against France's King Louis XIV early in the 18th century\n",
+ " * The War of the Austrian Succession in the 1740s\n",
+ " * The French and Indian War in the 1750's and 1760s\n",
+ " * The American War for Independence from 1775 to 1783\n",
+ "\n",
+ "Figure {numref}`fr_fig2` indicates that\n",
+ "\n",
+ " * during times of peace, government expenditures approximately equal taxes and debt service payments neither grow nor decline over time\n",
+ " * during times of wars, government expenditures exceed tax revenues\n",
+ " * the government finances the deficit of revenues relative to expenditures by issuing debt\n",
+ " * after a war is over, the government's tax revenues exceed its non-interest expenditures by just enough to service the debt that the government issued to finance earlier deficits\n",
+ " * thus, after a war, the government does *not* raise taxes by enough to pay off its debt\n",
+ " * instead, it just rolls over whatever debt it inherits, raising taxes by just enough to service the interest payments on that debt\n",
+ "\n",
+ "Eighteenth-century British fiscal policy portrayed Figure {numref}`fr_fig2` thus looks very much like a text-book example of a *tax-smoothing* model like Robert Barro's {cite}`Barro1979`. \n",
+ "\n",
+ "A striking feature of the graph is what we'll label a *law of gravity* between tax collections and government expenditures. \n",
+ "\n",
+ " * levels of government expenditures at taxes attract each other\n",
+ " * while they can temporarily differ -- as they do during wars -- they come back together when peace returns\n",
+ "\n",
+ "\n",
+ "\n",
+ "Next we'll plot data on debt service costs as fractions of government revenues in Great Britain and France during the 18th century."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a772e670",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Ratio of debt service to taxes, Britain and France",
+ "name": "fr_fig1"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Read the data from the Excel file\n",
+ "data1 = pd.read_excel(dette_url, sheet_name='Debt', \n",
+ " usecols='R:S', skiprows=5, nrows=99, header=None)\n",
+ "data1a = pd.read_excel(dette_url, sheet_name='Debt', \n",
+ " usecols='P', skiprows=89, nrows=15, header=None)\n",
+ "\n",
+ "# Plot the data\n",
+ "plt.figure()\n",
+ "plt.plot(range(1690, 1789), 100 * data1.iloc[:, 1], linewidth=0.8)\n",
+ "\n",
+ "date = np.arange(1690, 1789)\n",
+ "index = (date < 1774) & (data1.iloc[:, 0] > 0)\n",
+ "plt.plot(date[index], 100 * data1[index].iloc[:, 0], \n",
+ " '*:', color='r', linewidth=0.8)\n",
+ "\n",
+ "# Plot the additional data\n",
+ "plt.plot(range(1774, 1789), 100 * data1a, '*:', color='orange')\n",
+ "\n",
+ "# Note about the data\n",
+ "# The French data before 1720 don't match up with the published version\n",
+ "# Set the plot properties\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "plt.gca().set_facecolor('white')\n",
+ "plt.gca().set_xlim([1688, 1788])\n",
+ "plt.ylabel('% of Taxes')\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "816ae813",
+ "metadata": {},
+ "source": [
+ "Figure {numref}`fr_fig1` shows that interest payments on government debt (i.e., so-called ''debt service'') were high fractions of government tax revenues in both Great Britain and France. \n",
+ "\n",
+ "{numref}`fr_fig2` showed us that in peace times Britain managed to balance its budget despite those large interest costs. \n",
+ "\n",
+ "But as we'll see in our next graph, on the eve of the French Revolution in 1788, the fiscal *law of gravity* that worked so well in Britain did not working very well in France."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c5548306",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Read the data from the Excel file\n",
+ "data1 = pd.read_excel(fig_3_url, sheet_name='Sheet1', \n",
+ " usecols='C:F', skiprows=5, nrows=30, header=None)\n",
+ "\n",
+ "data1.replace(0, np.nan, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ccfd0f38",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Government Spending and Tax Revenues in France",
+ "name": "fr_fig3"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Plot the data\n",
+ "plt.figure()\n",
+ "\n",
+ "plt.plot(range(1759, 1789, 1), data1.iloc[:, 0], '-x', linewidth=0.8)\n",
+ "plt.plot(range(1759, 1789, 1), data1.iloc[:, 1], '--*', linewidth=0.8)\n",
+ "plt.plot(range(1759, 1789, 1), data1.iloc[:, 2], \n",
+ " '-o', linewidth=0.8, markerfacecolor='none')\n",
+ "plt.plot(range(1759, 1789, 1), data1.iloc[:, 3], '-*', linewidth=0.8)\n",
+ "\n",
+ "plt.text(1775, 610, 'total spending', fontsize=10)\n",
+ "plt.text(1773, 325, 'military', fontsize=10)\n",
+ "plt.text(1773, 220, 'civil plus debt service', fontsize=10)\n",
+ "plt.text(1773, 80, 'debt service', fontsize=10)\n",
+ "plt.text(1785, 500, 'revenues', fontsize=10)\n",
+ "\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "plt.ylim([0, 700])\n",
+ "plt.ylabel('millions of livres')\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "13c76c45",
+ "metadata": {},
+ "source": [
+ "{numref}`fr_fig3` shows that on the eve of the French Revolution in 1788, government expenditures exceeded tax revenues. \n",
+ "\n",
+ "\n",
+ "Especially during and after France's expenditures to help the Americans in their War of Independence from Great Britain, growing government debt service (i.e., interest payments) \n",
+ "contributed to this situation. \n",
+ "\n",
+ "This was partly a consequence of the unfolding of the debt dynamics that underlies the Unpleasant Arithmetic discussed in this quantecon lecture {doc}`unpleasant`. \n",
+ "\n",
+ "\n",
+ "{cite}`sargent_velde1995` describe how the Ancient Regime that until 1788 had governed France had stable institutional features that made it difficult for the government to balance its budget.\n",
+ "\n",
+ "Powerful contending interests had prevented from the government from closing the gap between its\n",
+ "total expenditures and its tax revenues by either\n",
+ "\n",
+ " * raising taxes, or\n",
+ " * lowering government's non-debt service (i.e., non-interest) expenditures, or \n",
+ " * lowering debt service (i.e., interest) costs by rescheduling, i.e., defaulting on some debts\n",
+ "\n",
+ "Precedents and prevailing French arrangements had empowered three constituencies to block adjustments to components of the government budget constraint that they cared especially about\n",
+ "\n",
+ "* tax payers\n",
+ "* beneficiaries of government expenditures\n",
+ "* government creditors (i.e., owners of government bonds)\n",
+ "\n",
+ "When the French government had confronted a similar situation around 1720 after King Louis XIV's\n",
+ "Wars had left it with a debt crisis, it had sacrificed the interests of \n",
+ "government creditors, i.e., by defaulting enough of its debt to bring reduce interest payments down enough to balance the budget.\n",
+ "\n",
+ "Somehow, in 1789, creditors of the French government were more powerful than they had been in 1720.\n",
+ "\n",
+ "Therefore, King Louis XVI convened the Estates General together to ask them to redesign the French constitution in a way that would lower government expenditures or increase taxes, thereby\n",
+ "allowing him to balance the budget while also honoring his promises to creditors of the French government. \n",
+ "\n",
+ "The King called the Estates General together in an effort to promote the reforms that would\n",
+ "would bring sustained budget balance. \n",
+ "\n",
+ "{cite}`sargent_velde1995` describe how the French Revolutionaries set out to accomplish that.\n",
+ "\n",
+ "## Nationalization, Privatization, Debt Reduction \n",
+ "\n",
+ "In 1789, the Revolutionaries quickly reorganized the Estates General into a National Assembly.\n",
+ "\n",
+ "A first piece of business was to address the fiscal crisis, the situation that had motivated the King to convene the Estates General.\n",
+ "\n",
+ "The Revolutionaries were not socialists or communists.\n",
+ "\n",
+ "To the contrary, they respected private property and knew state-of-the-art economics. \n",
+ "\n",
+ "They knew that to honor government debts, they would have to raise new revenues or reduce expenditures.\n",
+ "\n",
+ "A coincidence was that the Catholic Church owned vast income-producing properties. \n",
+ "\n",
+ "Indeed, the capitalized value of those income streams put estimates of the value of church lands at \n",
+ "about the same amount as the entire French government debt. \n",
+ "\n",
+ "This coincidence fostered a three step plan for servicing the French government debt\n",
+ "\n",
+ " * nationalize the church lands -- i.e., sequester or confiscate it without paying for it\n",
+ " * sell the church lands \n",
+ " * use the proceeds from those sales to service or even retire French government debt\n",
+ "\n",
+ "The monetary theory underlying this plan had been set out by Adam Smith in his analysis of what he called *real bills* in his 1776 book\n",
+ "**The Wealth of Nations** {cite}`smith2010wealth`, which many of the revolutionaries had read.\n",
+ "\n",
+ "Adam Smith defined a *real bill* as a paper money note that is backed by a claims on a real asset like productive capital or inventories. \n",
+ "\n",
+ "The National Assembly put together an ingenious institutional arrangement to implement this plan.\n",
+ "\n",
+ "In response to a motion by Catholic Bishop Talleyrand (an atheist),\n",
+ "the National Assembly confiscated and nationalized Church lands. \n",
+ "\n",
+ "The National Assembly intended to use earnings from Church lands to service its national debt.\n",
+ "\n",
+ "To do this, it began to implement a ''privatization plan'' that would let it service its debt while\n",
+ "not raising taxes.\n",
+ "\n",
+ "Their plan involved issuing paper notes called ''assignats'' that entitled bearers to use them to purchase state lands. \n",
+ "\n",
+ "These paper notes would be ''as good as silver coins'' in the sense that both were acceptable means of payment in exchange for those (formerly) church lands. \n",
+ "\n",
+ "Finance Minister Necker and the Constituents of the National Assembly thus planned\n",
+ "to solve the privatization problem *and* the debt problem simultaneously\n",
+ "by creating a new currency. \n",
+ "\n",
+ "They devised a scheme to raise revenues by auctioning\n",
+ "the confiscated lands, thereby withdrawing paper notes issued on the security of\n",
+ "the lands sold by the government.\n",
+ "\n",
+ " This ''tax-backed money'' scheme propelled the National Assembly into the domains of then modern monetary theories.\n",
+ " \n",
+ "Records of debates show\n",
+ "how members of the Assembly marshaled theory and evidence to assess the likely\n",
+ "effects of their innovation. \n",
+ "\n",
+ " * Members of the National Assembly quoted David Hume and Adam Smith\n",
+ " * They cited John Law's System of 1720 and the American experiences with paper money fifteen years\n",
+ "earlier as examples of how paper money schemes can go awry\n",
+ " * Knowing pitfalls, they set out to avoid them\n",
+ "\n",
+ "They succeeded for two or three years.\n",
+ "\n",
+ "But after that, France entered a big War that disrupted the plan in ways that completely altered the character of France's paper money. {cite}`sargent_velde1995` describe what happened.\n",
+ "\n",
+ "## Remaking the tax code and tax administration\n",
+ "\n",
+ "In 1789 the French Revolutionaries formed a National Assembly and set out to remake French\n",
+ "fiscal policy.\n",
+ "\n",
+ "They wanted to honor government debts -- interests of French government creditors were well represented in the National Assembly.\n",
+ "\n",
+ "But they set out to remake the French tax code and the administrative machinery for collecting taxes.\n",
+ "\n",
+ " * they abolished many taxes\n",
+ " * they abolished the Ancient Regimes scheme for *tax farming*\n",
+ " * tax farming meant that the government had privatized tax collection by hiring private citizens -- so-called tax farmers to collect taxes, while retaining a fraction of them as payment for their services\n",
+ " * the great chemist Lavoisier was also a tax farmer, one of the reasons that the Committee for Public Safety sent him to the guillotine in 1794\n",
+ "\n",
+ "As a consequence of these tax reforms, government tax revenues declined\n",
+ "\n",
+ "The next figure shows this"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e3ab0cb3",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Index of real per capital revenues, France",
+ "name": "fr_fig5"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Read data from Excel file\n",
+ "data5 = pd.read_excel(dette_url, sheet_name='Debt', usecols='K', \n",
+ " skiprows=41, nrows=120, header=None)\n",
+ "\n",
+ "# Plot the data\n",
+ "plt.figure()\n",
+ "plt.plot(range(1726, 1846), data5.iloc[:, 0], linewidth=0.8)\n",
+ "\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "plt.gca().set_facecolor('white')\n",
+ "plt.gca().tick_params(labelsize=12)\n",
+ "plt.xlim([1726, 1845])\n",
+ "plt.ylabel('1726 = 1', fontsize=12)\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "87cf3c9c",
+ "metadata": {},
+ "source": [
+ "According to {numref}`fr_fig5`, tax revenues per capita did not rise to their pre 1789 levels\n",
+ "until after 1815, when Napoleon Bonaparte was exiled to St Helena and King Louis XVIII was restored to the French Crown.\n",
+ "\n",
+ " * from 1799 to 1814, Napoleon Bonaparte had other sources of revenues -- booty and reparations from provinces and nations that he defeated in war\n",
+ "\n",
+ " * from 1789 to 1799, the French Revolutionaries turned to another source to raise resources to pay for government purchases of goods and services and to service French government debt. \n",
+ "\n",
+ "And as the next figure shows, government expenditures exceeded tax revenues by substantial\n",
+ "amounts during the period form 1789 to 1799."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "63b7bbcb",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Spending (blue) and Revenues (orange), (real values)",
+ "name": "fr_fig11"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Read data from Excel file\n",
+ "data11 = pd.read_excel(assignat_url, sheet_name='Budgets',\n",
+ " usecols='J:K', skiprows=22, nrows=52, header=None)\n",
+ "\n",
+ "# Prepare the x-axis data\n",
+ "x_data = np.concatenate([\n",
+ " np.arange(1791, 1794 + 8/12, 1/12),\n",
+ " np.arange(1794 + 9/12, 1795 + 3/12, 1/12)\n",
+ "])\n",
+ "\n",
+ "# Remove NaN values from the data\n",
+ "data11_clean = data11.dropna()\n",
+ "\n",
+ "# Plot the data\n",
+ "plt.figure()\n",
+ "h = plt.plot(x_data, data11_clean.values[:, 0], linewidth=0.8)\n",
+ "h = plt.plot(x_data, data11_clean.values[:, 1], '--', linewidth=0.8)\n",
+ "\n",
+ "# Set plot properties\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "plt.gca().set_facecolor('white')\n",
+ "plt.gca().tick_params(axis='both', which='major', labelsize=12)\n",
+ "plt.xlim([1791, 1795 + 3/12])\n",
+ "plt.xticks(np.arange(1791, 1796))\n",
+ "plt.yticks(np.arange(0, 201, 20))\n",
+ "\n",
+ "# Set the y-axis label\n",
+ "plt.ylabel('millions of livres', fontsize=12)\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9ec3dfae",
+ "metadata": {},
+ "source": [
+ "To cover the discrepancies between government expenditures and tax revenues revealed in {numref}`fr_fig11`, the French revolutionaries printed paper money and spent it. \n",
+ "\n",
+ "The next figure shows that by printing money, they were able to finance substantial purchases \n",
+ "of goods and services, including military goods and soldiers' pay."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "0c557a46",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Revenues raised by printing paper money notes",
+ "name": "fr_fig24"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Read data from Excel file\n",
+ "data12 = pd.read_excel(assignat_url, sheet_name='seignor', \n",
+ " usecols='F', skiprows=6, nrows=75, header=None).squeeze()\n",
+ "\n",
+ "# Create a figure and plot the data\n",
+ "plt.figure()\n",
+ "plt.plot(pd.date_range(start='1790', periods=len(data12), freq='M'),\n",
+ " data12, linewidth=0.8)\n",
+ "\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "\n",
+ "plt.axhline(y=472.42/12, color='r', linestyle=':')\n",
+ "plt.xticks(ticks=pd.date_range(start='1790', \n",
+ " end='1796', freq='AS'), labels=range(1790, 1797))\n",
+ "plt.xlim(pd.Timestamp('1791'),\n",
+ " pd.Timestamp('1796-02') + pd.DateOffset(months=2))\n",
+ "plt.ylabel('millions of livres', fontsize=12)\n",
+ "plt.text(pd.Timestamp('1793-11'), 39.5, 'revenues in 1788', \n",
+ " verticalalignment='top', fontsize=12)\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0f1e72f9",
+ "metadata": {},
+ "source": [
+ "{numref}`fr_fig24` compares the revenues raised by printing money from 1789 to 1796 with tax revenues that the Ancient Regime had raised in 1788.\n",
+ "\n",
+ "Measured in goods, revenues raised at time $t$ by printing new money equal\n",
+ "\n",
+ "$$\n",
+ "\\frac{M_{t+1} - M_t}{p_t}\n",
+ "$$\n",
+ "\n",
+ "where \n",
+ "\n",
+ "* $M_t$ is the stock of paper money at time $t$ measured in livres\n",
+ "* $p_t$ is the price level at time $t$ measured in units of goods per livre at time $t$\n",
+ "* $M_{t+1} - M_t$ is the amount of new money printed at time $t$\n",
+ "\n",
+ "Notice the 1793-1794 surge in revenues raised by printing money. \n",
+ "\n",
+ "* This reflects extraordinary measures that the Committee for Public Safety adopted to force citizens to accept paper money, or else.\n",
+ "\n",
+ "Also note the abrupt fall off in revenues raised by 1797 and the absence of further observations after 1797. \n",
+ "\n",
+ "* This reflects the end of using the printing press to raise revenues.\n",
+ "\n",
+ "What French paper money entitled its holders to changed over time in interesting ways.\n",
+ "\n",
+ "These led to outcomes that vary over time and that illustrate the playing out in practice of theories that guided the Revolutionaries' monetary policy decisions.\n",
+ "\n",
+ "\n",
+ "The next figure shows the price level in France during the time that the Revolutionaries used paper money to finance parts of their expenditures.\n",
+ "\n",
+ "Note that we use a log scale because the price level rose so much."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7172e0a7",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Price Level and Price of Gold (log scale)",
+ "name": "fr_fig9"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Read the data from Excel file\n",
+ "data7 = pd.read_excel(assignat_url, sheet_name='Data', \n",
+ " usecols='P:Q', skiprows=4, nrows=80, header=None)\n",
+ "data7a = pd.read_excel(assignat_url, sheet_name='Data', \n",
+ " usecols='L', skiprows=4, nrows=80, header=None)\n",
+ "# Create the figure and plot\n",
+ "plt.figure()\n",
+ "x = np.arange(1789 + 10/12, 1796 + 5/12, 1/12)\n",
+ "h, = plt.plot(x, 1. / data7.iloc[:, 0], linestyle='--')\n",
+ "h, = plt.plot(x, 1. / data7.iloc[:, 1], color='r')\n",
+ "\n",
+ "# Set properties of the plot\n",
+ "plt.gca().tick_params(labelsize=12)\n",
+ "plt.yscale('log')\n",
+ "plt.xlim([1789 + 10/12, 1796 + 5/12])\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "\n",
+ "# Add vertical lines\n",
+ "plt.axvline(x=1793 + 6.5/12, linestyle='-', linewidth=0.8, color='orange')\n",
+ "plt.axvline(x=1794 + 6.5/12, linestyle='-', linewidth=0.8, color='purple')\n",
+ "\n",
+ "# Add text\n",
+ "plt.text(1793.75, 120, 'Terror', fontsize=12)\n",
+ "plt.text(1795, 2.8, 'price level', fontsize=12)\n",
+ "plt.text(1794.9, 40, 'gold', fontsize=12)\n",
+ "\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "389e6e44",
+ "metadata": {},
+ "source": [
+ "We have partioned {numref}`fr_fig9` that shows the log of the price level and {numref}`fr_fig8`\n",
+ "below that plots real balances $\\frac{M_t}{p_t}$ into three periods that correspond to different monetary experiments or *regimes*. \n",
+ "\n",
+ "The first period ends in the late summer of 1793, and is characterized\n",
+ "by growing real balances and moderate inflation. \n",
+ "\n",
+ "The second period begins and ends\n",
+ "with the Terror. It is marked by high real balances, around 2,500 million, and\n",
+ "roughly stable prices. The fall of Robespierre in late July 1794 begins the third\n",
+ "of our episodes, in which real balances decline and prices rise rapidly.\n",
+ "\n",
+ "We interpret\n",
+ "these three episodes in terms of distinct theories\n",
+ "\n",
+ "* a *backing* or *real bills* theory (the classic text for this theory is Adam Smith {cite}`smith2010wealth`)\n",
+ "* a legal restrictions theory ( {cite}`keynes1940pay`, {cite}`bryant1984price` )\n",
+ "* a classical hyperinflation theory ({cite}`Cagan`)\n",
+ "* \n",
+ "```{note}\n",
+ "According to the empirical definition of hyperinflation adopted by {cite}`Cagan`,\n",
+ "beginning in the month that inflation exceeds 50 percent\n",
+ "per month and ending in the month before inflation drops below 50 percent per month\n",
+ "for at least a year, the *assignat* experienced a hyperinflation from May to December\n",
+ "1795.\n",
+ "```\n",
+ "We view these\n",
+ "theories not as competitors but as alternative collections of ''if-then''\n",
+ "statements about government note issues, each of which finds its conditions more\n",
+ "nearly met in one of these episodes than in the other two."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6dacee24",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Real balances of assignats (in gold and goods)",
+ "name": "fr_fig8"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Read the data from Excel file\n",
+ "data7 = pd.read_excel(assignat_url, sheet_name='Data', \n",
+ " usecols='P:Q', skiprows=4, nrows=80, header=None)\n",
+ "data7a = pd.read_excel(assignat_url, sheet_name='Data', \n",
+ " usecols='L', skiprows=4, nrows=80, header=None)\n",
+ "\n",
+ "# Create the figure and plot\n",
+ "plt.figure()\n",
+ "h = plt.plot(pd.date_range(start='1789-11-01', periods=len(data7), freq='M'), \n",
+ " (data7a.values * [1, 1]) * data7.values, linewidth=1.)\n",
+ "plt.setp(h[1], linestyle='--', color='red')\n",
+ "\n",
+ "plt.vlines([pd.Timestamp('1793-07-15'), pd.Timestamp('1793-07-15')], \n",
+ " 0, 3000, linewidth=0.8, color='orange')\n",
+ "plt.vlines([pd.Timestamp('1794-07-15'), pd.Timestamp('1794-07-15')], \n",
+ " 0, 3000, linewidth=0.8, color='purple')\n",
+ "\n",
+ "plt.ylim([0, 3000])\n",
+ "\n",
+ "# Set properties of the plot\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "plt.gca().set_facecolor('white')\n",
+ "plt.gca().tick_params(labelsize=12)\n",
+ "plt.xlim(pd.Timestamp('1789-11-01'), pd.Timestamp('1796-06-01'))\n",
+ "plt.ylabel('millions of livres', fontsize=12)\n",
+ "\n",
+ "# Add text annotations\n",
+ "plt.text(pd.Timestamp('1793-09-01'), 200, 'Terror', fontsize=12)\n",
+ "plt.text(pd.Timestamp('1791-05-01'), 750, 'gold value', fontsize=12)\n",
+ "plt.text(pd.Timestamp('1794-10-01'), 2500, 'real value', fontsize=12)\n",
+ "\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8a100368",
+ "metadata": {},
+ "source": [
+ "The three clouds of points in Figure\n",
+ "{numref}`fr_fig104`\n",
+ " depict different real balance-inflation relationships. \n",
+ " \n",
+ "Only the cloud for the\n",
+ "third period has the inverse relationship familiar to us now from twentieth-century\n",
+ "hyperinflations.\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "* subperiod 1: (\"*real bills* period): January 1791 to July 1793\n",
+ "\n",
+ "* subperiod 2: (\"terror\"): August 1793 - July 1794\n",
+ "\n",
+ "* subperiod 3: (\"classic Cagan hyperinflation\"): August 1794 - March 1796"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "03b15f1c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def fit(x, y):\n",
+ "\n",
+ " b = np.cov(x, y)[0, 1] / np.var(x)\n",
+ " a = y.mean() - b * x.mean()\n",
+ "\n",
+ " return a, b"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "adeec6ec",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Load data\n",
+ "caron = np.load('datasets/caron.npy')\n",
+ "nom_balances = np.load('datasets/nom_balances.npy')\n",
+ "\n",
+ "infl = np.concatenate(([np.nan], \n",
+ " -np.log(caron[1:63, 1] / caron[0:62, 1])))\n",
+ "bal = nom_balances[14:77, 1] * caron[:, 1] / 1000"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d3acc6d1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Regress y on x for three periods\n",
+ "a1, b1 = fit(bal[1:31], infl[1:31])\n",
+ "a2, b2 = fit(bal[31:44], infl[31:44])\n",
+ "a3, b3 = fit(bal[44:63], infl[44:63])\n",
+ "\n",
+ "# Regress x on y for three periods\n",
+ "a1_rev, b1_rev = fit(infl[1:31], bal[1:31])\n",
+ "a2_rev, b2_rev = fit(infl[31:44], bal[31:44])\n",
+ "a3_rev, b3_rev = fit(infl[44:63], bal[44:63])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "dbfd74fb",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Inflation and Real Balances",
+ "name": "fr_fig104"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "plt.figure()\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "\n",
+ "# First subsample\n",
+ "plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', \n",
+ " color='blue', label='real bills period')\n",
+ "\n",
+ "# Second subsample\n",
+ "plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror')\n",
+ "\n",
+ "# Third subsample\n",
+ "plt.plot(bal[44:63], infl[44:63], '*', \n",
+ " color='orange', label='classic Cagan hyperinflation')\n",
+ "\n",
+ "plt.xlabel('real balances')\n",
+ "plt.ylabel('inflation')\n",
+ "plt.legend()\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "693fca73",
+ "metadata": {},
+ "source": [
+ "The three clouds of points in {numref}`fr_fig104` evidently \n",
+ " depict different real balance-inflation relationships. \n",
+ "\n",
+ "Only the cloud for the\n",
+ "third period has the inverse relationship familiar to us now from twentieth-century\n",
+ "hyperinflations.\n",
+ "\n",
+ " To bring this out, we'll use linear regressions to draw straight lines that compress the \n",
+ " inflation-real balance relationship for our three sub-periods. \n",
+ "\n",
+ " Before we do that, we'll drop some of the early observations during the terror period \n",
+ " to obtain the following graph."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4307ce7d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Regress y on x for three periods\n",
+ "a1, b1 = fit(bal[1:31], infl[1:31])\n",
+ "a2, b2 = fit(bal[31:44], infl[31:44])\n",
+ "a3, b3 = fit(bal[44:63], infl[44:63])\n",
+ "\n",
+ "# Regress x on y for three periods\n",
+ "a1_rev, b1_rev = fit(infl[1:31], bal[1:31])\n",
+ "a2_rev, b2_rev = fit(infl[31:44], bal[31:44])\n",
+ "a3_rev, b3_rev = fit(infl[44:63], bal[44:63])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f39e161f",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Inflation and Real Balances",
+ "name": "fr_fig104b"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "plt.figure()\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "\n",
+ "# First subsample\n",
+ "plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period')\n",
+ "\n",
+ "# Second subsample\n",
+ "plt.plot(bal[34:44], infl[34:44], '+', color='red', label='terror')\n",
+ "\n",
+ "# Third subsample\n",
+ "plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation')\n",
+ "\n",
+ "plt.xlabel('real balances')\n",
+ "plt.ylabel('inflation')\n",
+ "plt.legend()\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "db7f3d32",
+ "metadata": {},
+ "source": [
+ "Now let's regress inflation on real balances during the *real bills* period and plot the regression\n",
+ "line."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "25fd1ba5",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Inflation and Real Balances",
+ "name": "fr_fig104c"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "plt.figure()\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "\n",
+ "# First subsample\n",
+ "plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', \n",
+ " color='blue', label='real bills period')\n",
+ "plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue')\n",
+ "\n",
+ "# Second subsample\n",
+ "plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror')\n",
+ "\n",
+ "# Third subsample\n",
+ "plt.plot(bal[44:63], infl[44:63], '*', \n",
+ " color='orange', label='classic Cagan hyperinflation')\n",
+ "\n",
+ "plt.xlabel('real balances')\n",
+ "plt.ylabel('inflation')\n",
+ "plt.legend()\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f68ca701",
+ "metadata": {},
+ "source": [
+ "The regression line in {numref}`fr_fig104c` shows that large increases in real balances of\n",
+ "assignats (paper money) were accompanied by only modest rises in the price level, an outcome in line\n",
+ "with the *real bills* theory. \n",
+ "\n",
+ "During this period, assignats were claims on church lands. \n",
+ "\n",
+ "But towards the end of this period, the price level started to rise and real balances to fall\n",
+ "as the government continued to print money but stopped selling church land. \n",
+ "\n",
+ "To get people to hold that paper money, the government forced people to hold it by using legal restrictions.\n",
+ "\n",
+ "Now let's regress real balances on inflation during the terror and plot the regression\n",
+ "line."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "53868900",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Inflation and Real Balances",
+ "name": "fr_fig104d"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "plt.figure()\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "\n",
+ "# First subsample\n",
+ "plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', \n",
+ " color='blue', label='real bills period')\n",
+ "\n",
+ "# Second subsample\n",
+ "plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror')\n",
+ "plt.plot(a2_rev + b2_rev * infl[31:44], infl[31:44], color='red')\n",
+ "\n",
+ "# Third subsample\n",
+ "plt.plot(bal[44:63], infl[44:63], '*', \n",
+ " color='orange', label='classic Cagan hyperinflation')\n",
+ "\n",
+ "plt.xlabel('real balances')\n",
+ "plt.ylabel('inflation')\n",
+ "plt.legend()\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1a4410a8",
+ "metadata": {},
+ "source": [
+ "The regression line in {numref}`fr_fig104d` shows that large increases in real balances of\n",
+ "assignats (paper money) were accompanied by little upward price level pressure, even some declines in prices. \n",
+ "\n",
+ "This reflects how well legal restrictions -- financial repression -- was working during the period of the Terror. \n",
+ "\n",
+ "But the Terror ended in July 1794. That unleashed a big inflation as people tried to find other ways to transact and store values. \n",
+ "\n",
+ "The following two graphs are for the classical hyperinflation period.\n",
+ "\n",
+ "One regresses inflation on real balances, the other regresses real balances on inflation.\n",
+ "\n",
+ "Both show a prounced inverse relationship that is the hallmark of the hyperinflations studied by \n",
+ "Cagan {cite}`Cagan`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1d8ee890",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Inflation and Real Balances",
+ "name": "fr_fig104e"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "plt.figure()\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "\n",
+ "# First subsample\n",
+ "plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', \n",
+ " color='blue', label='real bills period')\n",
+ "\n",
+ "# Second subsample\n",
+ "plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror')\n",
+ "\n",
+ "# Third subsample\n",
+ "plt.plot(bal[44:63], infl[44:63], '*', \n",
+ " color='orange', label='classic Cagan hyperinflation')\n",
+ "plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange')\n",
+ "\n",
+ "plt.xlabel('real balances')\n",
+ "plt.ylabel('inflation')\n",
+ "plt.legend()\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a71aff81",
+ "metadata": {},
+ "source": [
+ "{numref}`fr_fig104e` shows the results of regressing inflation on real balances during the\n",
+ "period of the hyperinflation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "50cc150a",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Inflation and Real Balances",
+ "name": "fr_fig104f"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "plt.figure()\n",
+ "plt.gca().spines['top'].set_visible(False)\n",
+ "plt.gca().spines['right'].set_visible(False)\n",
+ "\n",
+ "# First subsample\n",
+ "plt.plot(bal[1:31], infl[1:31], 'o', \n",
+ " markerfacecolor='none', color='blue', label='real bills period')\n",
+ "\n",
+ "# Second subsample\n",
+ "plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror')\n",
+ "\n",
+ "# Third subsample\n",
+ "plt.plot(bal[44:63], infl[44:63], '*', \n",
+ " color='orange', label='classic Cagan hyperinflation')\n",
+ "plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='orange')\n",
+ "\n",
+ "plt.xlabel('real balances')\n",
+ "plt.ylabel('inflation')\n",
+ "plt.legend()\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4dbc6470",
+ "metadata": {},
+ "source": [
+ "{numref}`fr_fig104e` shows the results of regressing real money balances on inflation during the\n",
+ "period of the hyperinflation.\n",
+ "\n",
+ "## Hyperinflation Ends\n",
+ "\n",
+ "{cite}`sargent_velde1995` tell how in 1797 the Revolutionary government abruptly ended the inflation by \n",
+ "\n",
+ " * repudiating 2/3 of the national debt, and thereby\n",
+ " * eliminating the net-of-interest government defict\n",
+ " * no longer printing money, but instead\n",
+ " * using gold and silver coins as money\n",
+ "\n",
+ "In 1799, Napoleon Bonaparte became first consul and for the next 15 years used resources confiscated from conquered territories to help pay for French government expenditures.\n",
+ "\n",
+ "## Underlying Theories\n",
+ "\n",
+ "This lecture sets the stage for studying theories of inflation and the government monetary and fiscal policies that bring it about.\n",
+ "\n",
+ "A *monetarist theory of the price level* is described in this quantecon lecture {doc}`cagan_ree`.\n",
+ "\n",
+ "That lecture sets the stage for these quantecon lectures {doc}`money_inflation` and {doc}`unpleasant`."
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.16.2"
+ }
+ },
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "source_map": [
+ 12,
+ 64,
+ 76,
+ 95,
+ 129,
+ 144,
+ 179,
+ 223,
+ 260,
+ 269,
+ 277,
+ 306,
+ 429,
+ 453,
+ 465,
+ 504,
+ 511,
+ 541,
+ 574,
+ 611,
+ 643,
+ 685,
+ 704,
+ 713,
+ 723,
+ 735,
+ 763,
+ 778,
+ 790,
+ 816,
+ 821,
+ 850,
+ 866,
+ 895,
+ 911,
+ 940,
+ 945,
+ 974
+ ]
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/french_rev.md b/book/_build/html/_sources/french_rev.md
new file mode 100644
index 0000000..1f5aec0
--- /dev/null
+++ b/book/_build/html/_sources/french_rev.md
@@ -0,0 +1,996 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.16.2
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+# Inflation During French Revolution
+
+
+## Overview
+
+This lecture describes some of the monetary and fiscal features of the French Revolution (1789-1799) described by {cite}`sargent_velde1995`.
+
+To finance public expenditures and service its debts,
+the French government embarked on policy experiments.
+
+The authors of these experiments had in mind theories about how government monetary and fiscal policies affected economic outcomes.
+
+Some of those theories about monetary and fiscal policies still interest us today.
+
+* a **tax-smoothing** model like Robert Barro's {cite}`Barro1979`
+
+ * this normative (i.e., prescriptive model) advises a government to finance temporary war-time surges in expenditures mostly by issuing government debt, raising taxes by just enough to service the additional debt issued during the wary; then, after the war, to roll over whatever debt the government had accumulated during the war; and to increase taxes after the war permanently by just enough to finance interest payments on that post-war government debt
+
+* **unpleasant monetarist arithmetic** like that described in this quanteon lecture {doc}`unpleasant`
+
+ * mathematics involving compound interest governed French government debt dynamics in the decades preceding 1789; according to leading historians, that arithmetic set the stage for the French Revolution
+
+* a *real bills* theory of the effects of government open market operations in which the government *backs* new issues of paper money with government holdings of valuable real property or financial assets that holders of money can purchase from the government in exchange for their money.
+
+ * The Revolutionaries learned about this theory from Adam Smith's 1776 book The Wealth of Nations
+ {cite}`smith2010wealth` and other contemporary sources
+
+ * It shaped how the Revolutionaries issued a paper money called **assignats** from 1789 to 1791
+
+* a classical **gold** or **silver standard**
+
+ * Napoleon Bonaparte became head of the French government in 1799. He used this theory to guide his monetary and fiscal policies
+
+* a classical **inflation-tax** theory of inflation in which Philip Cagan's ({cite}`Cagan`) demand for money studied in this lecture {doc}`cagan_ree` is a key component
+
+ * This theory helps explain French price level and money supply data from 1794 to 1797
+
+* a **legal restrictions** or **financial repression** theory of the demand for real balances
+
+ * The Twelve Members comprising the Committee of Public Safety who adminstered the Terror from June 1793 to July 1794 used this theory to shape their monetary policy
+
+We use matplotlib to replicate several of the graphs with which {cite}`sargent_velde1995` portrayed outcomes of these experiments
+
+## Data Sources
+
+This lecture uses data from three spreadsheets assembled by {cite}`sargent_velde1995`:
+ * [datasets/fig_3.xlsx](https://github.com/QuantEcon/lecture-python-intro/blob/main/lectures/datasets/fig_3.xlsx)
+ * [datasets/dette.xlsx](https://github.com/QuantEcon/lecture-python-intro/blob/main/lectures/datasets/dette.xlsx)
+ * [datasets/assignat.xlsx](https://github.com/QuantEcon/lecture-python-intro/blob/main/lectures/datasets/assignat.xlsx)
+
+```{code-cell} ipython3
+import numpy as np
+import pandas as pd
+import matplotlib.pyplot as plt
+plt.rcParams.update({'font.size': 12})
+
+base_url = 'https://github.com/QuantEcon/lecture-python-intro/raw/'\
+ + 'main/lectures/datasets/'
+
+fig_3_url = f'{base_url}fig_3.xlsx'
+dette_url = f'{base_url}dette.xlsx'
+assignat_url = f'{base_url}assignat.xlsx'
+```
+
+## Government Expenditures and Taxes Collected
+
+
+
+We'll start by using `matplotlib` to construct several graphs that will provide important historical context.
+
+These graphs are versions of ones that appear in {cite}`sargent_velde1995`.
+
+These graphs show that during the 18th century
+
+ * government expenditures in France and Great Britain both surged during four big wars, and by comparable amounts
+ * In Britain, tax revenues were approximately equal to government expenditures during peace times,
+ but were substantially less than government expenditures during wars
+ * In France, even in peace time, tax revenues were substantially less than government expenditures
+
+
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Military Spending in Britain and France"
+ name: fr_fig4
+---
+# Read the data from Excel file
+data2 = pd.read_excel(dette_url,
+ sheet_name='Militspe', usecols='M:X',
+ skiprows=7, nrows=102, header=None)
+
+# French military spending, 1685-1789, in 1726 livres
+data4 = pd.read_excel(dette_url,
+ sheet_name='Militspe', usecols='D',
+ skiprows=3, nrows=105, header=None).squeeze()
+
+years = range(1685, 1790)
+
+plt.figure()
+plt.plot(years, data4, '*-', linewidth=0.8)
+
+plt.plot(range(1689, 1791), data2.iloc[:, 4], linewidth=0.8)
+
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+plt.gca().tick_params(labelsize=12)
+plt.xlim([1689, 1790])
+plt.xlabel('*: France')
+plt.ylabel('Millions of livres')
+plt.ylim([0, 475])
+
+plt.tight_layout()
+plt.show()
+```
+
+During the 18th century, Britain and France fought four large wars.
+
+Britain won the first three wars and lost the fourth.
+
+Each of those wars produced surges in both countries' government expenditures that each country somehow had to finance.
+
+Figure {numref}`fr_fig4` shows surges in military expenditures in France (in blue) and Great Britain.
+during those four wars.
+
+A remarkable aspect of figure {numref}`fr_fig4` is that despite having a population less than half of France's, Britain was able to finance military expenses of about the same amounts as France's.
+
+This testifies to Britain's having created state institutions that could sustain high tax collections, government spending , and government borrowing. See {cite}`north1989`.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Government Expenditures and Tax Revenues in Britain"
+ name: fr_fig2
+---
+
+# Read the data from Excel file
+data2 = pd.read_excel(dette_url, sheet_name='Militspe', usecols='M:X',
+ skiprows=7, nrows=102, header=None)
+
+# Plot the data
+plt.figure()
+plt.plot(range(1689, 1791), data2.iloc[:, 5], linewidth=0.8)
+plt.plot(range(1689, 1791), data2.iloc[:, 11], linewidth=0.8, color='red')
+plt.plot(range(1689, 1791), data2.iloc[:, 9], linewidth=0.8, color='orange')
+plt.plot(range(1689, 1791), data2.iloc[:, 8], 'o-',
+ markerfacecolor='none', linewidth=0.8, color='purple')
+
+# Customize the plot
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+plt.gca().tick_params(labelsize=12)
+plt.xlim([1689, 1790])
+plt.ylabel('millions of pounds', fontsize=12)
+
+# Add text annotations
+plt.text(1765, 1.5, 'civil', fontsize=10)
+plt.text(1760, 4.2, 'civil plus debt service', fontsize=10)
+plt.text(1708, 15.5, 'total govt spending', fontsize=10)
+plt.text(1759, 7.3, 'revenues', fontsize=10)
+
+plt.tight_layout()
+plt.show()
+```
+
+
+Figures {numref}`fr_fig2` and {numref}`fr_fig3` summarize British and French government fiscal policies during the century before the start of the French Revolution in 1789.
+
+
+Before 1789, progressive forces in France admired how Britain had financed its government expenditures and wanted to redesign French fiscal arrangements to make them more like Britain's.
+
+Figure {numref}`fr_fig2` shows government expenditures and how it was distributed among expenditures for
+
+ * civil (non-military) activities
+ * debt service, i.e., interest payments
+ * military expenditures (the yellow line minus the red line)
+
+Figure {numref}`fr_fig2` also plots total government revenues from tax collections (the purple circled line)
+
+Notice the surges in total government expenditures associated with surges in military expenditures
+in these four wars
+
+ * Wars against France's King Louis XIV early in the 18th century
+ * The War of the Austrian Succession in the 1740s
+ * The French and Indian War in the 1750's and 1760s
+ * The American War for Independence from 1775 to 1783
+
+Figure {numref}`fr_fig2` indicates that
+
+ * during times of peace, government expenditures approximately equal taxes and debt service payments neither grow nor decline over time
+ * during times of wars, government expenditures exceed tax revenues
+ * the government finances the deficit of revenues relative to expenditures by issuing debt
+ * after a war is over, the government's tax revenues exceed its non-interest expenditures by just enough to service the debt that the government issued to finance earlier deficits
+ * thus, after a war, the government does *not* raise taxes by enough to pay off its debt
+ * instead, it just rolls over whatever debt it inherits, raising taxes by just enough to service the interest payments on that debt
+
+Eighteenth-century British fiscal policy portrayed Figure {numref}`fr_fig2` thus looks very much like a text-book example of a *tax-smoothing* model like Robert Barro's {cite}`Barro1979`.
+
+A striking feature of the graph is what we'll label a *law of gravity* between tax collections and government expenditures.
+
+ * levels of government expenditures at taxes attract each other
+ * while they can temporarily differ -- as they do during wars -- they come back together when peace returns
+
+
+
+Next we'll plot data on debt service costs as fractions of government revenues in Great Britain and France during the 18th century.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Ratio of debt service to taxes, Britain and France"
+ name: fr_fig1
+---
+
+# Read the data from the Excel file
+data1 = pd.read_excel(dette_url, sheet_name='Debt',
+ usecols='R:S', skiprows=5, nrows=99, header=None)
+data1a = pd.read_excel(dette_url, sheet_name='Debt',
+ usecols='P', skiprows=89, nrows=15, header=None)
+
+# Plot the data
+plt.figure()
+plt.plot(range(1690, 1789), 100 * data1.iloc[:, 1], linewidth=0.8)
+
+date = np.arange(1690, 1789)
+index = (date < 1774) & (data1.iloc[:, 0] > 0)
+plt.plot(date[index], 100 * data1[index].iloc[:, 0],
+ '*:', color='r', linewidth=0.8)
+
+# Plot the additional data
+plt.plot(range(1774, 1789), 100 * data1a, '*:', color='orange')
+
+# Note about the data
+# The French data before 1720 don't match up with the published version
+# Set the plot properties
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+plt.gca().set_facecolor('white')
+plt.gca().set_xlim([1688, 1788])
+plt.ylabel('% of Taxes')
+
+plt.tight_layout()
+plt.show()
+```
+
+Figure {numref}`fr_fig1` shows that interest payments on government debt (i.e., so-called ''debt service'') were high fractions of government tax revenues in both Great Britain and France.
+
+{numref}`fr_fig2` showed us that in peace times Britain managed to balance its budget despite those large interest costs.
+
+But as we'll see in our next graph, on the eve of the French Revolution in 1788, the fiscal *law of gravity* that worked so well in Britain did not working very well in France.
+
+
+```{code-cell} ipython3
+# Read the data from the Excel file
+data1 = pd.read_excel(fig_3_url, sheet_name='Sheet1',
+ usecols='C:F', skiprows=5, nrows=30, header=None)
+
+data1.replace(0, np.nan, inplace=True)
+```
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Government Spending and Tax Revenues in France"
+ name: fr_fig3
+---
+# Plot the data
+plt.figure()
+
+plt.plot(range(1759, 1789, 1), data1.iloc[:, 0], '-x', linewidth=0.8)
+plt.plot(range(1759, 1789, 1), data1.iloc[:, 1], '--*', linewidth=0.8)
+plt.plot(range(1759, 1789, 1), data1.iloc[:, 2],
+ '-o', linewidth=0.8, markerfacecolor='none')
+plt.plot(range(1759, 1789, 1), data1.iloc[:, 3], '-*', linewidth=0.8)
+
+plt.text(1775, 610, 'total spending', fontsize=10)
+plt.text(1773, 325, 'military', fontsize=10)
+plt.text(1773, 220, 'civil plus debt service', fontsize=10)
+plt.text(1773, 80, 'debt service', fontsize=10)
+plt.text(1785, 500, 'revenues', fontsize=10)
+
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+plt.ylim([0, 700])
+plt.ylabel('millions of livres')
+
+plt.tight_layout()
+plt.show()
+```
+
+{numref}`fr_fig3` shows that on the eve of the French Revolution in 1788, government expenditures exceeded tax revenues.
+
+
+Especially during and after France's expenditures to help the Americans in their War of Independence from Great Britain, growing government debt service (i.e., interest payments)
+contributed to this situation.
+
+This was partly a consequence of the unfolding of the debt dynamics that underlies the Unpleasant Arithmetic discussed in this quantecon lecture {doc}`unpleasant`.
+
+
+{cite}`sargent_velde1995` describe how the Ancient Regime that until 1788 had governed France had stable institutional features that made it difficult for the government to balance its budget.
+
+Powerful contending interests had prevented from the government from closing the gap between its
+total expenditures and its tax revenues by either
+
+ * raising taxes, or
+ * lowering government's non-debt service (i.e., non-interest) expenditures, or
+ * lowering debt service (i.e., interest) costs by rescheduling, i.e., defaulting on some debts
+
+Precedents and prevailing French arrangements had empowered three constituencies to block adjustments to components of the government budget constraint that they cared especially about
+
+* tax payers
+* beneficiaries of government expenditures
+* government creditors (i.e., owners of government bonds)
+
+When the French government had confronted a similar situation around 1720 after King Louis XIV's
+Wars had left it with a debt crisis, it had sacrificed the interests of
+government creditors, i.e., by defaulting enough of its debt to bring reduce interest payments down enough to balance the budget.
+
+Somehow, in 1789, creditors of the French government were more powerful than they had been in 1720.
+
+Therefore, King Louis XVI convened the Estates General together to ask them to redesign the French constitution in a way that would lower government expenditures or increase taxes, thereby
+allowing him to balance the budget while also honoring his promises to creditors of the French government.
+
+The King called the Estates General together in an effort to promote the reforms that would
+would bring sustained budget balance.
+
+{cite}`sargent_velde1995` describe how the French Revolutionaries set out to accomplish that.
+
+## Nationalization, Privatization, Debt Reduction
+
+In 1789, the Revolutionaries quickly reorganized the Estates General into a National Assembly.
+
+A first piece of business was to address the fiscal crisis, the situation that had motivated the King to convene the Estates General.
+
+The Revolutionaries were not socialists or communists.
+
+To the contrary, they respected private property and knew state-of-the-art economics.
+
+They knew that to honor government debts, they would have to raise new revenues or reduce expenditures.
+
+A coincidence was that the Catholic Church owned vast income-producing properties.
+
+Indeed, the capitalized value of those income streams put estimates of the value of church lands at
+about the same amount as the entire French government debt.
+
+This coincidence fostered a three step plan for servicing the French government debt
+
+ * nationalize the church lands -- i.e., sequester or confiscate it without paying for it
+ * sell the church lands
+ * use the proceeds from those sales to service or even retire French government debt
+
+The monetary theory underlying this plan had been set out by Adam Smith in his analysis of what he called *real bills* in his 1776 book
+**The Wealth of Nations** {cite}`smith2010wealth`, which many of the revolutionaries had read.
+
+Adam Smith defined a *real bill* as a paper money note that is backed by a claims on a real asset like productive capital or inventories.
+
+The National Assembly put together an ingenious institutional arrangement to implement this plan.
+
+In response to a motion by Catholic Bishop Talleyrand (an atheist),
+the National Assembly confiscated and nationalized Church lands.
+
+The National Assembly intended to use earnings from Church lands to service its national debt.
+
+To do this, it began to implement a ''privatization plan'' that would let it service its debt while
+not raising taxes.
+
+Their plan involved issuing paper notes called ''assignats'' that entitled bearers to use them to purchase state lands.
+
+These paper notes would be ''as good as silver coins'' in the sense that both were acceptable means of payment in exchange for those (formerly) church lands.
+
+Finance Minister Necker and the Constituents of the National Assembly thus planned
+to solve the privatization problem *and* the debt problem simultaneously
+by creating a new currency.
+
+They devised a scheme to raise revenues by auctioning
+the confiscated lands, thereby withdrawing paper notes issued on the security of
+the lands sold by the government.
+
+ This ''tax-backed money'' scheme propelled the National Assembly into the domains of then modern monetary theories.
+
+Records of debates show
+how members of the Assembly marshaled theory and evidence to assess the likely
+effects of their innovation.
+
+ * Members of the National Assembly quoted David Hume and Adam Smith
+ * They cited John Law's System of 1720 and the American experiences with paper money fifteen years
+earlier as examples of how paper money schemes can go awry
+ * Knowing pitfalls, they set out to avoid them
+
+They succeeded for two or three years.
+
+But after that, France entered a big War that disrupted the plan in ways that completely altered the character of France's paper money. {cite}`sargent_velde1995` describe what happened.
+
+## Remaking the tax code and tax administration
+
+In 1789 the French Revolutionaries formed a National Assembly and set out to remake French
+fiscal policy.
+
+They wanted to honor government debts -- interests of French government creditors were well represented in the National Assembly.
+
+But they set out to remake the French tax code and the administrative machinery for collecting taxes.
+
+ * they abolished many taxes
+ * they abolished the Ancient Regimes scheme for *tax farming*
+ * tax farming meant that the government had privatized tax collection by hiring private citizens -- so-called tax farmers to collect taxes, while retaining a fraction of them as payment for their services
+ * the great chemist Lavoisier was also a tax farmer, one of the reasons that the Committee for Public Safety sent him to the guillotine in 1794
+
+As a consequence of these tax reforms, government tax revenues declined
+
+The next figure shows this
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Index of real per capital revenues, France"
+ name: fr_fig5
+---
+# Read data from Excel file
+data5 = pd.read_excel(dette_url, sheet_name='Debt', usecols='K',
+ skiprows=41, nrows=120, header=None)
+
+# Plot the data
+plt.figure()
+plt.plot(range(1726, 1846), data5.iloc[:, 0], linewidth=0.8)
+
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+plt.gca().set_facecolor('white')
+plt.gca().tick_params(labelsize=12)
+plt.xlim([1726, 1845])
+plt.ylabel('1726 = 1', fontsize=12)
+
+plt.tight_layout()
+plt.show()
+```
+
+According to {numref}`fr_fig5`, tax revenues per capita did not rise to their pre 1789 levels
+until after 1815, when Napoleon Bonaparte was exiled to St Helena and King Louis XVIII was restored to the French Crown.
+
+ * from 1799 to 1814, Napoleon Bonaparte had other sources of revenues -- booty and reparations from provinces and nations that he defeated in war
+
+ * from 1789 to 1799, the French Revolutionaries turned to another source to raise resources to pay for government purchases of goods and services and to service French government debt.
+
+And as the next figure shows, government expenditures exceeded tax revenues by substantial
+amounts during the period form 1789 to 1799.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Spending (blue) and Revenues (orange), (real values)"
+ name: fr_fig11
+---
+# Read data from Excel file
+data11 = pd.read_excel(assignat_url, sheet_name='Budgets',
+ usecols='J:K', skiprows=22, nrows=52, header=None)
+
+# Prepare the x-axis data
+x_data = np.concatenate([
+ np.arange(1791, 1794 + 8/12, 1/12),
+ np.arange(1794 + 9/12, 1795 + 3/12, 1/12)
+])
+
+# Remove NaN values from the data
+data11_clean = data11.dropna()
+
+# Plot the data
+plt.figure()
+h = plt.plot(x_data, data11_clean.values[:, 0], linewidth=0.8)
+h = plt.plot(x_data, data11_clean.values[:, 1], '--', linewidth=0.8)
+
+# Set plot properties
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+plt.gca().set_facecolor('white')
+plt.gca().tick_params(axis='both', which='major', labelsize=12)
+plt.xlim([1791, 1795 + 3/12])
+plt.xticks(np.arange(1791, 1796))
+plt.yticks(np.arange(0, 201, 20))
+
+# Set the y-axis label
+plt.ylabel('millions of livres', fontsize=12)
+
+plt.tight_layout()
+plt.show()
+```
+
+To cover the discrepancies between government expenditures and tax revenues revealed in {numref}`fr_fig11`, the French revolutionaries printed paper money and spent it.
+
+The next figure shows that by printing money, they were able to finance substantial purchases
+of goods and services, including military goods and soldiers' pay.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Revenues raised by printing paper money notes"
+ name: fr_fig24
+---
+# Read data from Excel file
+data12 = pd.read_excel(assignat_url, sheet_name='seignor',
+ usecols='F', skiprows=6, nrows=75, header=None).squeeze()
+
+# Create a figure and plot the data
+plt.figure()
+plt.plot(pd.date_range(start='1790', periods=len(data12), freq='M'),
+ data12, linewidth=0.8)
+
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+
+plt.axhline(y=472.42/12, color='r', linestyle=':')
+plt.xticks(ticks=pd.date_range(start='1790',
+ end='1796', freq='AS'), labels=range(1790, 1797))
+plt.xlim(pd.Timestamp('1791'),
+ pd.Timestamp('1796-02') + pd.DateOffset(months=2))
+plt.ylabel('millions of livres', fontsize=12)
+plt.text(pd.Timestamp('1793-11'), 39.5, 'revenues in 1788',
+ verticalalignment='top', fontsize=12)
+
+plt.tight_layout()
+plt.show()
+```
+
+{numref}`fr_fig24` compares the revenues raised by printing money from 1789 to 1796 with tax revenues that the Ancient Regime had raised in 1788.
+
+Measured in goods, revenues raised at time $t$ by printing new money equal
+
+$$
+\frac{M_{t+1} - M_t}{p_t}
+$$
+
+where
+
+* $M_t$ is the stock of paper money at time $t$ measured in livres
+* $p_t$ is the price level at time $t$ measured in units of goods per livre at time $t$
+* $M_{t+1} - M_t$ is the amount of new money printed at time $t$
+
+Notice the 1793-1794 surge in revenues raised by printing money.
+
+* This reflects extraordinary measures that the Committee for Public Safety adopted to force citizens to accept paper money, or else.
+
+Also note the abrupt fall off in revenues raised by 1797 and the absence of further observations after 1797.
+
+* This reflects the end of using the printing press to raise revenues.
+
+What French paper money entitled its holders to changed over time in interesting ways.
+
+These led to outcomes that vary over time and that illustrate the playing out in practice of theories that guided the Revolutionaries' monetary policy decisions.
+
+
+The next figure shows the price level in France during the time that the Revolutionaries used paper money to finance parts of their expenditures.
+
+Note that we use a log scale because the price level rose so much.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Price Level and Price of Gold (log scale)"
+ name: fr_fig9
+---
+# Read the data from Excel file
+data7 = pd.read_excel(assignat_url, sheet_name='Data',
+ usecols='P:Q', skiprows=4, nrows=80, header=None)
+data7a = pd.read_excel(assignat_url, sheet_name='Data',
+ usecols='L', skiprows=4, nrows=80, header=None)
+# Create the figure and plot
+plt.figure()
+x = np.arange(1789 + 10/12, 1796 + 5/12, 1/12)
+h, = plt.plot(x, 1. / data7.iloc[:, 0], linestyle='--')
+h, = plt.plot(x, 1. / data7.iloc[:, 1], color='r')
+
+# Set properties of the plot
+plt.gca().tick_params(labelsize=12)
+plt.yscale('log')
+plt.xlim([1789 + 10/12, 1796 + 5/12])
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+
+# Add vertical lines
+plt.axvline(x=1793 + 6.5/12, linestyle='-', linewidth=0.8, color='orange')
+plt.axvline(x=1794 + 6.5/12, linestyle='-', linewidth=0.8, color='purple')
+
+# Add text
+plt.text(1793.75, 120, 'Terror', fontsize=12)
+plt.text(1795, 2.8, 'price level', fontsize=12)
+plt.text(1794.9, 40, 'gold', fontsize=12)
+
+
+plt.tight_layout()
+plt.show()
+```
+
+We have partioned {numref}`fr_fig9` that shows the log of the price level and {numref}`fr_fig8`
+below that plots real balances $\frac{M_t}{p_t}$ into three periods that correspond to different monetary experiments or *regimes*.
+
+The first period ends in the late summer of 1793, and is characterized
+by growing real balances and moderate inflation.
+
+The second period begins and ends
+with the Terror. It is marked by high real balances, around 2,500 million, and
+roughly stable prices. The fall of Robespierre in late July 1794 begins the third
+of our episodes, in which real balances decline and prices rise rapidly.
+
+We interpret
+these three episodes in terms of distinct theories
+
+* a *backing* or *real bills* theory (the classic text for this theory is Adam Smith {cite}`smith2010wealth`)
+* a legal restrictions theory ( {cite}`keynes1940pay`, {cite}`bryant1984price` )
+* a classical hyperinflation theory ({cite}`Cagan`)
+*
+```{note}
+According to the empirical definition of hyperinflation adopted by {cite}`Cagan`,
+beginning in the month that inflation exceeds 50 percent
+per month and ending in the month before inflation drops below 50 percent per month
+for at least a year, the *assignat* experienced a hyperinflation from May to December
+1795.
+```
+We view these
+theories not as competitors but as alternative collections of ''if-then''
+statements about government note issues, each of which finds its conditions more
+nearly met in one of these episodes than in the other two.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Real balances of assignats (in gold and goods)"
+ name: fr_fig8
+---
+# Read the data from Excel file
+data7 = pd.read_excel(assignat_url, sheet_name='Data',
+ usecols='P:Q', skiprows=4, nrows=80, header=None)
+data7a = pd.read_excel(assignat_url, sheet_name='Data',
+ usecols='L', skiprows=4, nrows=80, header=None)
+
+# Create the figure and plot
+plt.figure()
+h = plt.plot(pd.date_range(start='1789-11-01', periods=len(data7), freq='M'),
+ (data7a.values * [1, 1]) * data7.values, linewidth=1.)
+plt.setp(h[1], linestyle='--', color='red')
+
+plt.vlines([pd.Timestamp('1793-07-15'), pd.Timestamp('1793-07-15')],
+ 0, 3000, linewidth=0.8, color='orange')
+plt.vlines([pd.Timestamp('1794-07-15'), pd.Timestamp('1794-07-15')],
+ 0, 3000, linewidth=0.8, color='purple')
+
+plt.ylim([0, 3000])
+
+# Set properties of the plot
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+plt.gca().set_facecolor('white')
+plt.gca().tick_params(labelsize=12)
+plt.xlim(pd.Timestamp('1789-11-01'), pd.Timestamp('1796-06-01'))
+plt.ylabel('millions of livres', fontsize=12)
+
+# Add text annotations
+plt.text(pd.Timestamp('1793-09-01'), 200, 'Terror', fontsize=12)
+plt.text(pd.Timestamp('1791-05-01'), 750, 'gold value', fontsize=12)
+plt.text(pd.Timestamp('1794-10-01'), 2500, 'real value', fontsize=12)
+
+
+plt.tight_layout()
+plt.show()
+```
+
+The three clouds of points in Figure
+{numref}`fr_fig104`
+ depict different real balance-inflation relationships.
+
+Only the cloud for the
+third period has the inverse relationship familiar to us now from twentieth-century
+hyperinflations.
+
+
+
+
+* subperiod 1: ("*real bills* period): January 1791 to July 1793
+
+* subperiod 2: ("terror"): August 1793 - July 1794
+
+* subperiod 3: ("classic Cagan hyperinflation"): August 1794 - March 1796
+
+```{code-cell} ipython3
+def fit(x, y):
+
+ b = np.cov(x, y)[0, 1] / np.var(x)
+ a = y.mean() - b * x.mean()
+
+ return a, b
+```
+
+```{code-cell} ipython3
+# Load data
+caron = np.load('datasets/caron.npy')
+nom_balances = np.load('datasets/nom_balances.npy')
+
+infl = np.concatenate(([np.nan],
+ -np.log(caron[1:63, 1] / caron[0:62, 1])))
+bal = nom_balances[14:77, 1] * caron[:, 1] / 1000
+```
+
+```{code-cell} ipython3
+# Regress y on x for three periods
+a1, b1 = fit(bal[1:31], infl[1:31])
+a2, b2 = fit(bal[31:44], infl[31:44])
+a3, b3 = fit(bal[44:63], infl[44:63])
+
+# Regress x on y for three periods
+a1_rev, b1_rev = fit(infl[1:31], bal[1:31])
+a2_rev, b2_rev = fit(infl[31:44], bal[31:44])
+a3_rev, b3_rev = fit(infl[44:63], bal[44:63])
+```
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Inflation and Real Balances"
+ name: fr_fig104
+---
+plt.figure()
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+
+# First subsample
+plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none',
+ color='blue', label='real bills period')
+
+# Second subsample
+plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror')
+
+# Third subsample
+plt.plot(bal[44:63], infl[44:63], '*',
+ color='orange', label='classic Cagan hyperinflation')
+
+plt.xlabel('real balances')
+plt.ylabel('inflation')
+plt.legend()
+
+plt.tight_layout()
+plt.show()
+```
+
+The three clouds of points in {numref}`fr_fig104` evidently
+ depict different real balance-inflation relationships.
+
+Only the cloud for the
+third period has the inverse relationship familiar to us now from twentieth-century
+hyperinflations.
+
+ To bring this out, we'll use linear regressions to draw straight lines that compress the
+ inflation-real balance relationship for our three sub-periods.
+
+ Before we do that, we'll drop some of the early observations during the terror period
+ to obtain the following graph.
+
+```{code-cell} ipython3
+# Regress y on x for three periods
+a1, b1 = fit(bal[1:31], infl[1:31])
+a2, b2 = fit(bal[31:44], infl[31:44])
+a3, b3 = fit(bal[44:63], infl[44:63])
+
+# Regress x on y for three periods
+a1_rev, b1_rev = fit(infl[1:31], bal[1:31])
+a2_rev, b2_rev = fit(infl[31:44], bal[31:44])
+a3_rev, b3_rev = fit(infl[44:63], bal[44:63])
+```
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Inflation and Real Balances"
+ name: fr_fig104b
+---
+plt.figure()
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+
+# First subsample
+plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period')
+
+# Second subsample
+plt.plot(bal[34:44], infl[34:44], '+', color='red', label='terror')
+
+# Third subsample
+plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation')
+
+plt.xlabel('real balances')
+plt.ylabel('inflation')
+plt.legend()
+
+plt.tight_layout()
+plt.show()
+```
+
+Now let's regress inflation on real balances during the *real bills* period and plot the regression
+line.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Inflation and Real Balances"
+ name: fr_fig104c
+---
+plt.figure()
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+
+# First subsample
+plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none',
+ color='blue', label='real bills period')
+plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue')
+
+# Second subsample
+plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror')
+
+# Third subsample
+plt.plot(bal[44:63], infl[44:63], '*',
+ color='orange', label='classic Cagan hyperinflation')
+
+plt.xlabel('real balances')
+plt.ylabel('inflation')
+plt.legend()
+
+plt.tight_layout()
+plt.show()
+```
+
+The regression line in {numref}`fr_fig104c` shows that large increases in real balances of
+assignats (paper money) were accompanied by only modest rises in the price level, an outcome in line
+with the *real bills* theory.
+
+During this period, assignats were claims on church lands.
+
+But towards the end of this period, the price level started to rise and real balances to fall
+as the government continued to print money but stopped selling church land.
+
+To get people to hold that paper money, the government forced people to hold it by using legal restrictions.
+
+Now let's regress real balances on inflation during the terror and plot the regression
+line.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Inflation and Real Balances"
+ name: fr_fig104d
+---
+plt.figure()
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+
+# First subsample
+plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none',
+ color='blue', label='real bills period')
+
+# Second subsample
+plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror')
+plt.plot(a2_rev + b2_rev * infl[31:44], infl[31:44], color='red')
+
+# Third subsample
+plt.plot(bal[44:63], infl[44:63], '*',
+ color='orange', label='classic Cagan hyperinflation')
+
+plt.xlabel('real balances')
+plt.ylabel('inflation')
+plt.legend()
+
+plt.tight_layout()
+plt.show()
+```
+
+The regression line in {numref}`fr_fig104d` shows that large increases in real balances of
+assignats (paper money) were accompanied by little upward price level pressure, even some declines in prices.
+
+This reflects how well legal restrictions -- financial repression -- was working during the period of the Terror.
+
+But the Terror ended in July 1794. That unleashed a big inflation as people tried to find other ways to transact and store values.
+
+The following two graphs are for the classical hyperinflation period.
+
+One regresses inflation on real balances, the other regresses real balances on inflation.
+
+Both show a prounced inverse relationship that is the hallmark of the hyperinflations studied by
+Cagan {cite}`Cagan`.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Inflation and Real Balances"
+ name: fr_fig104e
+---
+plt.figure()
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+
+# First subsample
+plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none',
+ color='blue', label='real bills period')
+
+# Second subsample
+plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror')
+
+# Third subsample
+plt.plot(bal[44:63], infl[44:63], '*',
+ color='orange', label='classic Cagan hyperinflation')
+plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange')
+
+plt.xlabel('real balances')
+plt.ylabel('inflation')
+plt.legend()
+
+plt.tight_layout()
+plt.show()
+```
+
+{numref}`fr_fig104e` shows the results of regressing inflation on real balances during the
+period of the hyperinflation.
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Inflation and Real Balances"
+ name: fr_fig104f
+---
+plt.figure()
+plt.gca().spines['top'].set_visible(False)
+plt.gca().spines['right'].set_visible(False)
+
+# First subsample
+plt.plot(bal[1:31], infl[1:31], 'o',
+ markerfacecolor='none', color='blue', label='real bills period')
+
+# Second subsample
+plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror')
+
+# Third subsample
+plt.plot(bal[44:63], infl[44:63], '*',
+ color='orange', label='classic Cagan hyperinflation')
+plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='orange')
+
+plt.xlabel('real balances')
+plt.ylabel('inflation')
+plt.legend()
+
+plt.tight_layout()
+plt.show()
+```
+
+{numref}`fr_fig104e` shows the results of regressing real money balances on inflation during the
+period of the hyperinflation.
+
+## Hyperinflation Ends
+
+{cite}`sargent_velde1995` tell how in 1797 the Revolutionary government abruptly ended the inflation by
+
+ * repudiating 2/3 of the national debt, and thereby
+ * eliminating the net-of-interest government defict
+ * no longer printing money, but instead
+ * using gold and silver coins as money
+
+In 1799, Napoleon Bonaparte became first consul and for the next 15 years used resources confiscated from conquered territories to help pay for French government expenditures.
+
+## Underlying Theories
+
+This lecture sets the stage for studying theories of inflation and the government monetary and fiscal policies that bring it about.
+
+A *monetarist theory of the price level* is described in this quantecon lecture {doc}`cagan_ree`.
+
+That lecture sets the stage for these quantecon lectures {doc}`money_inflation` and {doc}`unpleasant`.
diff --git a/content/lectures/geom_series.ipynb b/book/_build/html/_sources/geom_series.ipynb
similarity index 94%
rename from content/lectures/geom_series.ipynb
rename to book/_build/html/_sources/geom_series.ipynb
index c03a75c..ee279f3 100644
--- a/content/lectures/geom_series.ipynb
+++ b/book/_build/html/_sources/geom_series.ipynb
@@ -2,11 +2,11 @@
"cells": [
{
"cell_type": "markdown",
- "id": "226cf3d1",
+ "id": "dad4c518",
"metadata": {},
"source": [
"(geom_series)=\n",
- "```{raw} html\n",
+ "```{raw} jupyter\n",
"\n",
"```\n",
"\n",
- "# {index}`Dynamics in One Dimension `\n",
+ "(scalar_dynam)=\n",
+ "# Dynamics in One Dimension\n",
"\n",
- "```{contents} Contents\n",
- ":depth: 2\n",
- "```\n",
"\n",
"## Overview\n",
"\n",
- "In this lecture we give a quick introduction to discrete time dynamics in one dimension.\n",
+ "In economics many variables depend on their past values\n",
+ "\n",
+ "For example, it seems reasonable to believe that inflation last year with affects inflation this year.\n",
+ "\n",
+ "(Perhaps high inflation last year will lead people to demand higher wages to\n",
+ "compensate, which will feed into higher prices this year.)\n",
+ "\n",
+ "Letting $\\pi_t$ be inflation this year and $\\pi_{t-1}$ be inflation last year, we\n",
+ "can write this relationship in a general form as\n",
"\n",
- "* In one-dimensional models, the state of the system is described by a single variable.\n",
- "* The variable is a number (that is, a point in $\\mathbb R$).\n",
+ "$$ \\pi_t = f(\\pi_{t-1}) $$\n",
"\n",
- "While most quantitative models have two or more state variables, the\n",
- "one-dimensional setting is a good place to learn the foundations of dynamics\n",
- "and understand key concepts.\n",
+ "where $f$ is some function describing the relationship between the variables.\n",
+ "\n",
+ "This equation is an example of one-dimensional discrete time dynamic system.\n",
+ "\n",
+ "In this lecture we cover the foundations of one-dimensional discrete time\n",
+ "dynamics.\n",
+ "\n",
+ "(While most quantitative models have two or more state variables, the\n",
+ "one-dimensional setting is a good place to learn foundations \n",
+ "and understand key concepts.)\n",
"\n",
"Let's start with some standard imports:"
]
@@ -36,25 +48,24 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "c5aeb01a",
+ "id": "98362056",
"metadata": {},
"outputs": [],
"source": [
- "%matplotlib inline\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
- "id": "b4dcd341",
+ "id": "2b076430",
"metadata": {},
"source": [
- "## Some Definitions\n",
+ "## Some definitions\n",
"\n",
"This section sets out the objects of interest and the kinds of properties we study.\n",
"\n",
- "### Composition of Functions\n",
+ "### Composition of functions\n",
"\n",
"For this lecture you should know the following.\n",
"\n",
@@ -84,14 +95,14 @@
" f^2(x) = \\sqrt{\\sqrt{x}} = x^{1/4}\n",
"$$\n",
"\n",
- "Similarly, if $n$ is an integer, then $f^n$ is $n$ compositions of $f$ with\n",
+ "Similarly, if $n$ is a positive integer, then $f^n$ is $n$ compositions of $f$ with\n",
"itself.\n",
"\n",
"In the example above, $f^n(x) = x^{1/(2^n)}$.\n",
"\n",
"\n",
"\n",
- "### Dynamic Systems\n",
+ "### Dynamic systems\n",
"\n",
"A **(discrete time) dynamic system** is a set $S$ and a function $g$ that sends\n",
"set $S$ back into to itself.\n",
@@ -109,10 +120,6 @@
"\n",
"* $g$ does not always send points in $S$ back into $S$.\n",
"\n",
- "\n",
- "\n",
- "### Dynamic Systems\n",
- "\n",
"We care about dynamic systems because we can use them to study dynamics!\n",
"\n",
"Given a dynamic system consisting of set $S$ and function $g$, we can create\n",
@@ -143,7 +150,7 @@
"we can write the trajectory more simply as \n",
"\n",
"$$\n",
- " x_t = g^t(x_0) \\quad \\text{ for } t \\geq 0.\n",
+ " x_t = g^t(x_0) \\quad \\text{ for } t = 0, 1, 2, \\ldots\n",
"$$\n",
"\n",
"In all of what follows, we are going to assume that $S$ is a subset of\n",
@@ -155,10 +162,10 @@
"\n",
"\n",
"\n",
- "### Example: A Linear Model\n",
+ "### Example: a linear model\n",
"\n",
"One simple example of a dynamic system is when $S=\\mathbb R$ and $g(x)=ax +\n",
- "b$, where $a, b$ are fixed constants.\n",
+ "b$, where $a, b$ are constants (sometimes called ``parameters'').\n",
"\n",
"This leads to the **linear difference equation**\n",
"\n",
@@ -180,14 +187,14 @@
"```\n",
"\n",
"Continuing in this way, and using our knowledge of {doc}`geometric series\n",
- "`, we find that, for any $t \\geq 0$,\n",
+ "`, we find that, for any $t = 0, 1, 2, \\ldots$,\n",
"\n",
"```{math}\n",
":label: sdslinmod\n",
" x_t = a^t x_0 + b \\frac{1 - a^t}{1 - a}\n",
"```\n",
"\n",
- "We have an exact expression for $x_t$ for all $t$ and hence a full\n",
+ "We have an exact expression for $x_t$ for all non-negative integer $t$ and hence a full\n",
"understanding of the dynamics.\n",
"\n",
"Notice in particular that $|a| < 1$, then, by {eq}`sdslinmod`, we have\n",
@@ -198,7 +205,7 @@
"x_t \\to \\frac{b}{1 - a} \\text{ as } t \\to \\infty\n",
"```\n",
"\n",
- "regardless of $x_0$\n",
+ "regardless of $x_0$.\n",
"\n",
"This is an example of what is called global stability, a topic we return to\n",
"below.\n",
@@ -206,25 +213,26 @@
"\n",
"\n",
"\n",
- "### Example: A Nonlinear Model\n",
+ "### Example: a nonlinear model\n",
"\n",
"In the linear example above, we obtained an exact analytical expression for\n",
- "$x_t$ in terms of arbitrary $t$ and $x_0$.\n",
+ "$x_t$ in terms of arbitrary non-negative integer $t$ and $x_0$.\n",
"\n",
"This made analysis of dynamics very easy.\n",
"\n",
"When models are nonlinear, however, the situation can be quite different.\n",
"\n",
- "For example, recall how we [previously studied](https://python-programming.quantecon.org/python_oop.html#example-the-solow-growth-model) the law of motion for the Solow growth model, a simplified version of which is\n",
+ "For example, in a later lecture {doc}`solow`, we will study the Solow-Swan growth model, which has dynamics \n",
"\n",
"```{math}\n",
":label: solow_lom2\n",
"\n",
- "k_{t+1} = s z k_t^{\\alpha} + (1 - \\delta) k_t\n",
+ "k_{t+1} = s A k_t^{\\alpha} + (1 - \\delta) k_t\n",
"```\n",
"\n",
- "Here $k$ is capital stock and $s, z, \\alpha, \\delta$ are positive\n",
- "parameters with $0 < \\alpha, \\delta < 1$.\n",
+ "Here $k=K/L$ is the per capita capital stock, $s$ is the saving rate, $A$ is the total factor productivity, $\\alpha$ is the capital share, and $\\delta$ is the depreciation rate. \n",
+ "\n",
+ "All these parameter are positive and $0 < \\alpha, \\delta < 1$.\n",
"\n",
"If you try to iterate like we did in {eq}`sdslinmodpath`, you will find that\n",
"the algebra gets messy quickly.\n",
@@ -238,10 +246,11 @@
"\n",
"## Stability\n",
"\n",
- "Consider a fixed dynamic system consisting of set $S \\subset \\mathbb R$ and\n",
+ "Consider a dynamic system consisting of set $S \\subset \\mathbb R$ and\n",
"$g$ mapping $S$ to $S$.\n",
"\n",
- "### Steady States\n",
+ "(scalar-dynam:steady-state)=\n",
+ "### Steady states\n",
"\n",
"A **steady state** of this system is a\n",
"point $x^*$ in $S$ such that $x^* = g(x^*)$.\n",
@@ -252,15 +261,16 @@
"For example, for the linear model $x_{t+1} = a x_t + b$, you can use the\n",
"definition to check that\n",
"\n",
- "* $x^* := b/(1-a)$ is a steady state whenever $a \\not= 1$.\n",
+ "* $x^* := b/(1-a)$ is a steady state whenever $a \\not= 1$,\n",
"* if $a = 1$ and $b=0$, then every $x \\in \\mathbb R$ is a\n",
- " steady state.\n",
+ " steady state,\n",
"* if $a = 1$ and $b \\not= 0$, then the linear model has no steady\n",
" state in $\\mathbb R$.\n",
"\n",
"\n",
"\n",
- "### Global Stability\n",
+ "(scalar-dynam:global-stability)=\n",
+ "### Global stability\n",
"\n",
"A steady state $x^*$ of the dynamic system is called\n",
"**globally stable** if, for all $x_0 \\in S$,\n",
@@ -278,7 +288,7 @@
"This follows directly from {eq}`sdslinmod`.\n",
"\n",
"\n",
- "### Local Stability\n",
+ "### Local stability\n",
"\n",
"A steady state $x^*$ of the dynamic system is called\n",
"**locally stable** if there exists an $\\epsilon > 0$ such that\n",
@@ -291,15 +301,20 @@
"\n",
"Obviously every globally stable steady state is also locally stable.\n",
"\n",
- "We will see examples below where the converse is not true.\n",
- "\n",
+ "Here is an example where the converse is not true.\n",
"\n",
+ "```{prf:example}\n",
+ "Consider the self-map $g$ on $\\mathbb{R}$ defined by $g(x)=x^2$. The fixed point $1$ is not stable.\n",
"\n",
+ "For example, $g^t (x)\\to\\infty$ for any $x>1$.\n",
"\n",
+ "However, $0$ is locally stable, because $-1 k_t$.\n",
- "* If $g$ lies below the 45 degree line at this point, then we have $k_{t+1} < k_t$.\n",
- "* 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.\n",
+ "* If $g$ lies above the 45-degree line at this point, then we have $k_{t+1} > k_t$.\n",
+ "* If $g$ lies below the 45-degree line at this point, then we have $k_{t+1} < k_t$.\n",
+ "* 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.\n",
"\n",
- "For the Solow model, there are two steady states when $S = \\mathbb R_+ =\n",
+ "For the Solow-Swan model, there are two steady states when $S = \\mathbb R_+ =\n",
"[0, \\infty)$.\n",
"\n",
"* the origin $k=0$\n",
@@ -504,7 +503,7 @@
"\n",
"### Trajectories\n",
"\n",
- "By the preceding discussion, in regions where $g$ lies above the 45 degree line, we know that the trajectory is increasing.\n",
+ "By the preceding discussion, in regions where $g$ lies above the 45-degree line, we know that the trajectory is increasing.\n",
"\n",
"The next figure traces out a trajectory in such a region so we can see this more clearly.\n",
"\n",
@@ -514,7 +513,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "f293fe5f",
+ "id": "2e76b8e9",
"metadata": {},
"outputs": [],
"source": [
@@ -525,17 +524,17 @@
},
{
"cell_type": "markdown",
- "id": "526f96a6",
+ "id": "384b411f",
"metadata": {},
"source": [
- "We can plot the time series of capital corresponding to the figure above as\n",
+ "We can plot the time series of per capita capital corresponding to the figure above as\n",
"follows:"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "5b2c618d",
+ "id": "603c391a",
"metadata": {},
"outputs": [],
"source": [
@@ -544,7 +543,7 @@
},
{
"cell_type": "markdown",
- "id": "3c0fb1cc",
+ "id": "d2bbaefa",
"metadata": {},
"source": [
"Here's a somewhat longer view:"
@@ -553,7 +552,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "cbbc075a",
+ "id": "cc7d795c",
"metadata": {},
"outputs": [],
"source": [
@@ -562,17 +561,17 @@
},
{
"cell_type": "markdown",
- "id": "282d3c6c",
+ "id": "7e7ea40b",
"metadata": {},
"source": [
- "When capital stock is higher than the unique positive steady state, we see that\n",
+ "When per capita capital stock is higher than the unique positive steady state, we see that\n",
"it declines:"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "3e1745a9",
+ "id": "a861dfee",
"metadata": {},
"outputs": [],
"source": [
@@ -583,7 +582,7 @@
},
{
"cell_type": "markdown",
- "id": "b41d401b",
+ "id": "1bde242d",
"metadata": {},
"source": [
"Here is the time series:"
@@ -592,7 +591,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "ed74945a",
+ "id": "3e1a3683",
"metadata": {},
"outputs": [],
"source": [
@@ -601,12 +600,12 @@
},
{
"cell_type": "markdown",
- "id": "ba27a40c",
+ "id": "bc2b6cee",
"metadata": {},
"source": [
- "### Complex Dynamics\n",
+ "### Complex dynamics\n",
"\n",
- "The Solow model is nonlinear but still generates very regular dynamics.\n",
+ "The Solow-Swan model is nonlinear but still generates very regular dynamics.\n",
"\n",
"One model that generates irregular dynamics is the **quadratic map**\n",
"\n",
@@ -615,13 +614,13 @@
"\\qquad x \\in [0, 1]\n",
"$$\n",
"\n",
- "Let's have a look at the 45 degree diagram."
+ "Let's have a look at the 45-degree diagram."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "6b2cec7f",
+ "id": "890f95fa",
"metadata": {},
"outputs": [],
"source": [
@@ -634,7 +633,7 @@
},
{
"cell_type": "markdown",
- "id": "c78f4034",
+ "id": "ac9664ec",
"metadata": {},
"source": [
"Now let's look at a typical trajectory."
@@ -643,7 +642,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "4b0c3f3e",
+ "id": "886fe677",
"metadata": {},
"outputs": [],
"source": [
@@ -652,7 +651,7 @@
},
{
"cell_type": "markdown",
- "id": "0f41740d",
+ "id": "c02a1c4b",
"metadata": {},
"source": [
"Notice how irregular it is.\n",
@@ -663,7 +662,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "36006f35",
+ "id": "9d3a4167",
"metadata": {},
"outputs": [],
"source": [
@@ -672,7 +671,7 @@
},
{
"cell_type": "markdown",
- "id": "ab57f653",
+ "id": "9025fd5e",
"metadata": {},
"source": [
"The irregularity is even clearer over a longer time horizon:"
@@ -681,7 +680,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "3f244342",
+ "id": "d3812d88",
"metadata": {},
"outputs": [],
"source": [
@@ -690,7 +689,7 @@
},
{
"cell_type": "markdown",
- "id": "ae34e800",
+ "id": "221f0730",
"metadata": {},
"source": [
"## Exercises\n",
@@ -710,7 +709,7 @@
"What differences do you notice in the cases $a \\in (-1, 0)$ and $a\n",
"\\in (0, 1)$?\n",
"\n",
- "Use $a=0.5$ and then $a=-0.5$ and study the trajectories\n",
+ "Use $a=0.5$ and then $a=-0.5$ and study the trajectories.\n",
"\n",
"Set $b=1$ throughout.\n",
"```\n",
@@ -727,7 +726,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "83c74276",
+ "id": "0887907f",
"metadata": {},
"outputs": [],
"source": [
@@ -738,7 +737,7 @@
},
{
"cell_type": "markdown",
- "id": "ad663fd2",
+ "id": "18f4b021",
"metadata": {},
"source": [
"Now let's plot a trajectory:"
@@ -747,7 +746,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "6d8a689a",
+ "id": "3bec2603",
"metadata": {},
"outputs": [],
"source": [
@@ -757,7 +756,7 @@
},
{
"cell_type": "markdown",
- "id": "58e69a62",
+ "id": "946d881e",
"metadata": {},
"source": [
"Here is the corresponding time series, which converges towards the steady\n",
@@ -767,7 +766,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "248b2dc3",
+ "id": "9a53fe6d",
"metadata": {},
"outputs": [],
"source": [
@@ -776,7 +775,7 @@
},
{
"cell_type": "markdown",
- "id": "4c20cca1",
+ "id": "63ec18f2",
"metadata": {},
"source": [
"Now let's try $a=-0.5$ and see what differences we observe.\n",
@@ -787,7 +786,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "c8ea1d41",
+ "id": "28b8c13f",
"metadata": {},
"outputs": [],
"source": [
@@ -798,7 +797,7 @@
},
{
"cell_type": "markdown",
- "id": "d786395a",
+ "id": "3074e458",
"metadata": {},
"source": [
"Now let's plot a trajectory:"
@@ -807,7 +806,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "de161be2",
+ "id": "81fd6aa5",
"metadata": {},
"outputs": [],
"source": [
@@ -817,7 +816,7 @@
},
{
"cell_type": "markdown",
- "id": "89e7419b",
+ "id": "5fbff293",
"metadata": {},
"source": [
"Here is the corresponding time series, which converges towards the steady\n",
@@ -827,7 +826,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "dc7fd851",
+ "id": "73d3a1d3",
"metadata": {},
"outputs": [],
"source": [
@@ -836,7 +835,7 @@
},
{
"cell_type": "markdown",
- "id": "393972ac",
+ "id": "0ac7c4fd",
"metadata": {},
"source": [
"Once again, we have convergence to the steady state but the nature of\n",
@@ -853,12 +852,59 @@
}
],
"metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst"
+ }
+ },
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
- }
+ },
+ "source_map": [
+ 10,
+ 51,
+ 54,
+ 330,
+ 419,
+ 424,
+ 427,
+ 431,
+ 435,
+ 470,
+ 474,
+ 479,
+ 481,
+ 485,
+ 487,
+ 492,
+ 496,
+ 500,
+ 502,
+ 517,
+ 523,
+ 527,
+ 529,
+ 535,
+ 537,
+ 541,
+ 543,
+ 575,
+ 579,
+ 583,
+ 586,
+ 591,
+ 593,
+ 599,
+ 603,
+ 607,
+ 610,
+ 615,
+ 617
+ ]
},
"nbformat": 4,
"nbformat_minor": 5
-}
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/scalar_dynam.md b/book/_build/html/_sources/scalar_dynam.md
new file mode 100644
index 0000000..5926a3f
--- /dev/null
+++ b/book/_build/html/_sources/scalar_dynam.md
@@ -0,0 +1,628 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+kernelspec:
+ display_name: Python 3
+ language: python
+ name: python3
+---
+
+```{raw} html
+
+```
+
+(scalar_dynam)=
+# Dynamics in One Dimension
+
+
+## Overview
+
+In economics many variables depend on their past values
+
+For example, it seems reasonable to believe that inflation last year with affects inflation this year.
+
+(Perhaps high inflation last year will lead people to demand higher wages to
+compensate, which will feed into higher prices this year.)
+
+Letting $\pi_t$ be inflation this year and $\pi_{t-1}$ be inflation last year, we
+can write this relationship in a general form as
+
+$$ \pi_t = f(\pi_{t-1}) $$
+
+where $f$ is some function describing the relationship between the variables.
+
+This equation is an example of one-dimensional discrete time dynamic system.
+
+In this lecture we cover the foundations of one-dimensional discrete time
+dynamics.
+
+(While most quantitative models have two or more state variables, the
+one-dimensional setting is a good place to learn foundations
+and understand key concepts.)
+
+Let's start with some standard imports:
+
+```{code-cell} ipython
+import matplotlib.pyplot as plt
+import numpy as np
+```
+
+
+## Some definitions
+
+This section sets out the objects of interest and the kinds of properties we study.
+
+### Composition of functions
+
+For this lecture you should know the following.
+
+If
+
+* $g$ is a function from $A$ to $B$ and
+* $f$ is a function from $B$ to $C$,
+
+then the **composition** $f \circ g$ of $f$ and $g$ is defined by
+
+$$
+ (f \circ g)(x) = f(g(x))
+$$
+
+For example, if
+
+* $A=B=C=\mathbb R$, the set of real numbers,
+* $g(x)=x^2$ and $f(x)=\sqrt{x}$, then $(f \circ g)(x) = \sqrt{x^2} = |x|$.
+
+If $f$ is a function from $A$ to itself, then $f^2$ is the composition of $f$
+with itself.
+
+For example, if $A = (0, \infty)$, the set of positive numbers, and $f(x) =
+\sqrt{x}$, then
+
+$$
+ f^2(x) = \sqrt{\sqrt{x}} = x^{1/4}
+$$
+
+Similarly, if $n$ is a positive integer, then $f^n$ is $n$ compositions of $f$ with
+itself.
+
+In the example above, $f^n(x) = x^{1/(2^n)}$.
+
+
+
+### Dynamic systems
+
+A **(discrete time) dynamic system** is a set $S$ and a function $g$ that sends
+set $S$ back into to itself.
+
+
+Examples of dynamic systems include
+
+* $S = (0, 1)$ and $g(x) = \sqrt{x}$
+* $S = (0, 1)$ and $g(x) = x^2$
+* $S = \mathbb Z$ (the integers) and $g(x) = 2 x$
+
+
+On the other hand, if $S = (-1, 1)$ and $g(x) = x+1$, then $S$ and $g$ do not
+form a dynamic system, since $g(1) = 2$.
+
+* $g$ does not always send points in $S$ back into $S$.
+
+We care about dynamic systems because we can use them to study dynamics!
+
+Given a dynamic system consisting of set $S$ and function $g$, we can create
+a sequence $\{x_t\}$ of points in $S$ by setting
+
+```{math}
+:label: sdsod
+ x_{t+1} = g(x_t)
+ \quad \text{ with }
+ x_0 \text{ given}.
+```
+
+This means that we choose some number $x_0$ in $S$ and then take
+
+```{math}
+:label: sdstraj
+ x_0, \quad
+ x_1 = g(x_0), \quad
+ x_2 = g(x_1) = g(g(x_0)), \quad \text{etc.}
+```
+
+This sequence $\{x_t\}$ is called the **trajectory** of $x_0$ under $g$.
+
+In this setting, $S$ is called the **state space** and $x_t$ is called the
+**state variable**.
+
+Recalling that $g^n$ is the $n$ compositions of $g$ with itself,
+we can write the trajectory more simply as
+
+$$
+ x_t = g^t(x_0) \quad \text{ for } t = 0, 1, 2, \ldots
+$$
+
+In all of what follows, we are going to assume that $S$ is a subset of
+$\mathbb R$, the real numbers.
+
+Equation {eq}`sdsod` is sometimes called a **first order difference equation**
+
+* first order means dependence on only one lag (i.e., earlier states such as $x_{t-1}$ do not enter into {eq}`sdsod`).
+
+
+
+### Example: a linear model
+
+One simple example of a dynamic system is when $S=\mathbb R$ and $g(x)=ax +
+b$, where $a, b$ are constants (sometimes called ``parameters'').
+
+This leads to the **linear difference equation**
+
+$$
+ x_{t+1} = a x_t + b
+ \quad \text{ with }
+ x_0 \text{ given}.
+$$
+
+
+The trajectory of $x_0$ is
+
+```{math}
+:label: sdslinmodpath
+
+x_0, \quad
+a x_0 + b, \quad
+a^2 x_0 + a b + b, \quad \text{etc.}
+```
+
+Continuing in this way, and using our knowledge of {doc}`geometric series
+`, we find that, for any $t = 0, 1, 2, \ldots$,
+
+```{math}
+:label: sdslinmod
+ x_t = a^t x_0 + b \frac{1 - a^t}{1 - a}
+```
+
+We have an exact expression for $x_t$ for all non-negative integer $t$ and hence a full
+understanding of the dynamics.
+
+Notice in particular that $|a| < 1$, then, by {eq}`sdslinmod`, we have
+
+```{math}
+:label: sdslinmodc
+
+x_t \to \frac{b}{1 - a} \text{ as } t \to \infty
+```
+
+regardless of $x_0$.
+
+This is an example of what is called global stability, a topic we return to
+below.
+
+
+
+
+### Example: a nonlinear model
+
+In the linear example above, we obtained an exact analytical expression for
+$x_t$ in terms of arbitrary non-negative integer $t$ and $x_0$.
+
+This made analysis of dynamics very easy.
+
+When models are nonlinear, however, the situation can be quite different.
+
+For example, in a later lecture {doc}`solow`, we will study the Solow-Swan growth model, which has dynamics
+
+```{math}
+:label: solow_lom2
+
+k_{t+1} = s A k_t^{\alpha} + (1 - \delta) k_t
+```
+
+Here $k=K/L$ is the per capita capital stock, $s$ is the saving rate, $A$ is the total factor productivity, $\alpha$ is the capital share, and $\delta$ is the depreciation rate.
+
+All these parameter are positive and $0 < \alpha, \delta < 1$.
+
+If you try to iterate like we did in {eq}`sdslinmodpath`, you will find that
+the algebra gets messy quickly.
+
+Analyzing the dynamics of this model requires a different method (see below).
+
+
+
+
+
+
+## Stability
+
+Consider a dynamic system consisting of set $S \subset \mathbb R$ and
+$g$ mapping $S$ to $S$.
+
+(scalar-dynam:steady-state)=
+### Steady states
+
+A **steady state** of this system is a
+point $x^*$ in $S$ such that $x^* = g(x^*)$.
+
+In other words, $x^*$ is a **fixed point** of the function $g$ in
+$S$.
+
+For example, for the linear model $x_{t+1} = a x_t + b$, you can use the
+definition to check that
+
+* $x^* := b/(1-a)$ is a steady state whenever $a \not= 1$,
+* if $a = 1$ and $b=0$, then every $x \in \mathbb R$ is a
+ steady state,
+* if $a = 1$ and $b \not= 0$, then the linear model has no steady
+ state in $\mathbb R$.
+
+
+
+(scalar-dynam:global-stability)=
+### Global stability
+
+A steady state $x^*$ of the dynamic system is called
+**globally stable** if, for all $x_0 \in S$,
+
+$$
+x_t = g^t(x_0) \to x^* \text{ as } t \to \infty
+$$
+
+For example, in the linear model $x_{t+1} = a x_t + b$ with $a
+\not= 1$, the steady state $x^*$
+
+* is globally stable if $|a| < 1$ and
+* fails to be globally stable otherwise.
+
+This follows directly from {eq}`sdslinmod`.
+
+
+### Local stability
+
+A steady state $x^*$ of the dynamic system is called
+**locally stable** if there exists an $\epsilon > 0$ such that
+
+$$
+| x_0 - x^* | < \epsilon
+\; \implies \;
+x_t = g^t(x_0) \to x^* \text{ as } t \to \infty
+$$
+
+Obviously every globally stable steady state is also locally stable.
+
+Here is an example where the converse is not true.
+
+```{prf:example}
+Consider the self-map $g$ on $\mathbb{R}$ defined by $g(x)=x^2$. The fixed point $1$ is not stable.
+
+For example, $g^t (x)\to\infty$ for any $x>1$.
+
+However, $0$ is locally stable, because $-1 k_t$.
+* If $g$ lies below the 45-degree line at this point, then we have $k_{t+1} < k_t$.
+* 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.
+
+For the Solow-Swan model, there are two steady states when $S = \mathbb R_+ =
+[0, \infty)$.
+
+* the origin $k=0$
+* the unique positive number such that $k = s z k^{\alpha} + (1 - \delta) k$.
+
+By using some algebra, we can show that in the second case, the steady state is
+
+$$
+k^* = \left( \frac{sz}{\delta} \right)^{1/(1-\alpha)}
+$$
+
+### Trajectories
+
+By the preceding discussion, in regions where $g$ lies above the 45-degree line, we know that the trajectory is increasing.
+
+The next figure traces out a trajectory in such a region so we can see this more clearly.
+
+The initial condition is $k_0 = 0.25$.
+
+```{code-cell} ipython
+k0 = 0.25
+
+plot45(g, xmin, xmax, k0, num_arrows=5, var='k')
+```
+
+We can plot the time series of per capita capital corresponding to the figure above as
+follows:
+
+```{code-cell} ipython
+ts_plot(g, xmin, xmax, k0, var='k')
+```
+
+Here's a somewhat longer view:
+
+```{code-cell} ipython
+ts_plot(g, xmin, xmax, k0, ts_length=20, var='k')
+```
+
+When per capita capital stock is higher than the unique positive steady state, we see that
+it declines:
+
+```{code-cell} ipython
+k0 = 2.95
+
+plot45(g, xmin, xmax, k0, num_arrows=5, var='k')
+```
+
+Here is the time series:
+
+```{code-cell} ipython
+ts_plot(g, xmin, xmax, k0, var='k')
+```
+
+### Complex dynamics
+
+The Solow-Swan model is nonlinear but still generates very regular dynamics.
+
+One model that generates irregular dynamics is the **quadratic map**
+
+$$
+g(x) = 4 x (1 - x),
+\qquad x \in [0, 1]
+$$
+
+Let's have a look at the 45-degree diagram.
+
+```{code-cell} ipython
+xmin, xmax = 0, 1
+g = lambda x: 4 * x * (1 - x)
+
+x0 = 0.3
+plot45(g, xmin, xmax, x0, num_arrows=0)
+```
+
+Now let's look at a typical trajectory.
+
+```{code-cell} ipython
+plot45(g, xmin, xmax, x0, num_arrows=6)
+```
+
+Notice how irregular it is.
+
+Here is the corresponding time series plot.
+
+```{code-cell} ipython
+ts_plot(g, xmin, xmax, x0, ts_length=6)
+```
+
+The irregularity is even clearer over a longer time horizon:
+
+```{code-cell} ipython
+ts_plot(g, xmin, xmax, x0, ts_length=20)
+```
+
+## Exercises
+
+```{exercise}
+:label: sd_ex1
+
+Consider again the linear model $x_{t+1} = a x_t + b$ with $a
+\not=1$.
+
+The unique steady state is $b / (1 - a)$.
+
+The steady state is globally stable if $|a| < 1$.
+
+Try to illustrate this graphically by looking at a range of initial conditions.
+
+What differences do you notice in the cases $a \in (-1, 0)$ and $a
+\in (0, 1)$?
+
+Use $a=0.5$ and then $a=-0.5$ and study the trajectories.
+
+Set $b=1$ throughout.
+```
+
+```{solution-start} sd_ex1
+:class: dropdown
+```
+
+We will start with the case $a=0.5$.
+
+Let's set up the model and plotting region:
+
+```{code-cell} ipython
+a, b = 0.5, 1
+xmin, xmax = -1, 3
+g = lambda x: a * x + b
+```
+
+Now let's plot a trajectory:
+
+```{code-cell} ipython
+x0 = -0.5
+plot45(g, xmin, xmax, x0, num_arrows=5)
+```
+
+Here is the corresponding time series, which converges towards the steady
+state.
+
+```{code-cell} ipython
+ts_plot(g, xmin, xmax, x0, ts_length=10)
+```
+
+Now let's try $a=-0.5$ and see what differences we observe.
+
+Let's set up the model and plotting region:
+
+```{code-cell} ipython
+a, b = -0.5, 1
+xmin, xmax = -1, 3
+g = lambda x: a * x + b
+```
+
+Now let's plot a trajectory:
+
+```{code-cell} ipython
+x0 = -0.5
+plot45(g, xmin, xmax, x0, num_arrows=5)
+```
+
+Here is the corresponding time series, which converges towards the steady
+state.
+
+```{code-cell} ipython
+ts_plot(g, xmin, xmax, x0, ts_length=10)
+```
+
+Once again, we have convergence to the steady state but the nature of
+convergence differs.
+
+In particular, the time series jumps from above the steady state to below it
+and back again.
+
+In the current context, the series is said to exhibit **damped oscillations**.
+
+```{solution-end}
+```
diff --git a/content/lectures/schelling.ipynb b/book/_build/html/_sources/schelling.ipynb
similarity index 91%
rename from content/lectures/schelling.ipynb
rename to book/_build/html/_sources/schelling.ipynb
index 06957d1..69681db 100644
--- a/content/lectures/schelling.ipynb
+++ b/book/_build/html/_sources/schelling.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "54c2700e",
+ "id": "638e64a9",
"metadata": {},
"source": [
"(schelling)=\n",
@@ -14,7 +14,7 @@
"\n",
"```\n",
"\n",
- "# Racial Segregation \n",
+ "# Racial Segregation\n",
"\n",
"```{index} single: Schelling Segregation Model\n",
"```\n",
@@ -22,10 +22,6 @@
"```{index} single: Models; Schelling's Segregation Model\n",
"```\n",
"\n",
- "```{contents} Contents\n",
- ":depth: 2\n",
- "```\n",
- "\n",
"## Outline\n",
"\n",
"In 1969, Thomas C. Schelling developed a simple but striking model of racial\n",
@@ -67,11 +63,10 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "1fe33c76",
+ "id": "0bd481b7",
"metadata": {},
"outputs": [],
"source": [
- "%matplotlib inline\n",
"import matplotlib.pyplot as plt\n",
"from random import uniform, seed\n",
"from math import sqrt\n",
@@ -80,10 +75,10 @@
},
{
"cell_type": "markdown",
- "id": "a727e04a",
+ "id": "72be2419",
"metadata": {},
"source": [
- "## The Model\n",
+ "## The model\n",
"\n",
"In this section we will build a version of Schelling's model.\n",
"\n",
@@ -108,7 +103,7 @@
},
{
"cell_type": "markdown",
- "id": "a80eff12",
+ "id": "630c963a",
"metadata": {},
"source": [
"### Preferences\n",
@@ -131,7 +126,7 @@
},
{
"cell_type": "markdown",
- "id": "e45e0c71",
+ "id": "e37c4052",
"metadata": {},
"source": [
"### Behavior\n",
@@ -167,7 +162,7 @@
},
{
"cell_type": "markdown",
- "id": "b924cffb",
+ "id": "b78fa2b7",
"metadata": {},
"source": [
"## Results\n",
@@ -197,7 +192,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "4bb1628e",
+ "id": "39a62ad8",
"metadata": {},
"outputs": [],
"source": [
@@ -216,30 +211,30 @@
" b = (self.location[1] - other.location[1])**2\n",
" return sqrt(a + b)\n",
"\n",
- " def happy(self, \n",
+ " def happy(self,\n",
" agents, # List of other agents\n",
" num_neighbors=10, # No. of agents viewed as neighbors\n",
" require_same_type=5): # How many neighbors must be same type\n",
" \"\"\"\n",
" True if a sufficient number of nearest neighbors are of the same\n",
- " type. \n",
+ " type.\n",
" \"\"\"\n",
"\n",
" distances = []\n",
- " \n",
+ "\n",
" # Distances is a list of pairs (d, agent), where d is distance from\n",
" # agent to self\n",
" for agent in agents:\n",
" if self != agent:\n",
" distance = self.get_distance(agent)\n",
" distances.append((distance, agent))\n",
- " \n",
+ "\n",
" # Sort from smallest to largest, according to distance\n",
" distances.sort()\n",
- " \n",
+ "\n",
" # Extract the neighboring agents\n",
" neighbors = [agent for d, agent in distances[:num_neighbors]]\n",
- " \n",
+ "\n",
" # Count how many neighbors have the same type as self\n",
" num_same_type = sum(self.type == agent.type for agent in neighbors)\n",
" return num_same_type >= require_same_type\n",
@@ -252,7 +247,7 @@
},
{
"cell_type": "markdown",
- "id": "384b5ea3",
+ "id": "dc47a542",
"metadata": {},
"source": [
"Here's some code that takes a list of agents and produces a plot showing their\n",
@@ -265,7 +260,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "5d1bcf81",
+ "id": "2119c858",
"metadata": {},
"outputs": [],
"source": [
@@ -285,9 +280,9 @@
" fig, ax = plt.subplots()\n",
" plot_args = {'markersize': 8, 'alpha': 0.8}\n",
" ax.set_facecolor('azure')\n",
- " ax.plot(x_values_0, y_values_0, \n",
+ " ax.plot(x_values_0, y_values_0,\n",
" 'o', markerfacecolor='orange', **plot_args)\n",
- " ax.plot(x_values_1, y_values_1, \n",
+ " ax.plot(x_values_1, y_values_1,\n",
" 'o', markerfacecolor='green', **plot_args)\n",
" ax.set_title(f'Cycle {cycle_num-1}')\n",
" plt.show()"
@@ -295,7 +290,7 @@
},
{
"cell_type": "markdown",
- "id": "34284ec1",
+ "id": "81de02d5",
"metadata": {},
"source": [
"And here's some pseudocode for the main loop, where we cycle through the\n",
@@ -317,18 +312,18 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "12c1ec53",
+ "id": "61e87234",
"metadata": {},
"outputs": [],
"source": [
"def run_simulation(num_of_type_0=600,\n",
" num_of_type_1=600,\n",
- " max_iter=100_000, # Maximum number of iterations \n",
- " set_seed=1234): \n",
+ " max_iter=100_000, # Maximum number of iterations\n",
+ " set_seed=1234):\n",
"\n",
" # Set the seed for reproducibility\n",
- " seed(set_seed) \n",
- " \n",
+ " seed(set_seed)\n",
+ "\n",
" # Create a list of agents of type 0\n",
" agents = [Agent(0) for i in range(num_of_type_0)]\n",
" # Append a list of agents of type 1\n",
@@ -336,11 +331,11 @@
"\n",
" # Initialize a counter\n",
" count = 1\n",
- " \n",
+ "\n",
" # Plot the initial distribution\n",
" plot_distribution(agents, count)\n",
- " \n",
- " # Loop until no agent wishes to move \n",
+ "\n",
+ " # Loop until no agent wishes to move\n",
" while count < max_iter:\n",
" print('Entering loop ', count)\n",
" count += 1\n",
@@ -352,20 +347,19 @@
" no_one_moved = False\n",
" if no_one_moved:\n",
" break\n",
- " \n",
+ "\n",
" # Plot final distribution\n",
" plot_distribution(agents, count)\n",
"\n",
" if count < max_iter:\n",
" print(f'Converged after {count} iterations.')\n",
" else:\n",
- " print('Hit iteration bound and terminated.')\n",
- " "
+ " print('Hit iteration bound and terminated.')\n"
]
},
{
"cell_type": "markdown",
- "id": "73ae91c2",
+ "id": "a7b1bb7a",
"metadata": {},
"source": [
"Let's have a look at the results."
@@ -374,7 +368,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "0f2eefd4",
+ "id": "d1dbd1c4",
"metadata": {},
"outputs": [],
"source": [
@@ -383,7 +377,7 @@
},
{
"cell_type": "markdown",
- "id": "31194751",
+ "id": "5d887438",
"metadata": {},
"source": [
"As discussed above, agents are initially mixed randomly together.\n",
@@ -412,7 +406,7 @@
"optimize than procedural code (i.e., code based around functions rather than\n",
"objects and methods).\n",
"\n",
- "Try writing a new version of the model that stores \n",
+ "Try writing a new version of the model that stores\n",
"\n",
"* the locations of all agents as a 2D NumPy array of floats.\n",
"* the types of all agents as a flat NumPy array of integers.\n",
@@ -443,12 +437,11 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "61addfdd",
+ "id": "9e4f7f73",
"metadata": {},
"outputs": [],
"source": [
"from numpy.random import uniform, randint\n",
- "from numba import njit\n",
"\n",
"n = 1000 # number of agents (agents = 0, ..., n-1)\n",
"k = 10 # number of agents regarded as neighbors\n",
@@ -459,13 +452,10 @@
" types = randint(0, high=2, size=n) # label zero or one\n",
" return locations, types\n",
"\n",
- "@njit # Use Numba to accelerate computation\n",
+ "\n",
"def compute_distances_from_loc(loc, locations):\n",
- " \" Compute distance from location loc to all other points. \"\n",
- " distances = np.empty(n)\n",
- " for j in range(n):\n",
- " distances[j] = np.linalg.norm(loc - locations[j, :])\n",
- " return distances\n",
+ " \"\"\" Compute distance from location loc to all other points. \"\"\"\n",
+ " return np.linalg.norm(loc - locations, axis=1)\n",
"\n",
"def get_neighbors(loc, locations):\n",
" \" Get all neighbors of a given location. \"\n",
@@ -490,7 +480,7 @@
" for i in range(n):\n",
" happy_sum += is_happy(i, locations, types)\n",
" return happy_sum\n",
- " \n",
+ "\n",
"def update_agent(i, locations, types):\n",
" \" Move agent if unhappy. \"\n",
" moved = False\n",
@@ -505,11 +495,11 @@
" colors = 'orange', 'green'\n",
" for agent_type, color in zip((0, 1), colors):\n",
" idx = (types == agent_type)\n",
- " ax.plot(locations[idx, 0], \n",
- " locations[idx, 1], \n",
- " 'o', \n",
+ " ax.plot(locations[idx, 0],\n",
+ " locations[idx, 1],\n",
+ " 'o',\n",
" markersize=8,\n",
- " markerfacecolor=color, \n",
+ " markerfacecolor=color,\n",
" alpha=0.8)\n",
" ax.set_title(title)\n",
" plt.show()\n",
@@ -531,7 +521,7 @@
" i = randint(0, n)\n",
" moved = update_agent(i, locations, types)\n",
"\n",
- " if flip_prob > 0: \n",
+ " if flip_prob > 0:\n",
" # flip agent i's type with probability epsilon\n",
" U = uniform()\n",
" if U < flip_prob:\n",
@@ -539,7 +529,7 @@
" types[i] = 0 if current_type == 1 else 1\n",
"\n",
" # Every so many updates, plot and test for convergence\n",
- " if current_iter % test_freq == 0: \n",
+ " if current_iter % test_freq == 0:\n",
" cycle = current_iter / n\n",
" plot_distribution(locations, types, f'iteration {current_iter}')\n",
" if count_happy(locations, types) == n:\n",
@@ -554,7 +544,7 @@
},
{
"cell_type": "markdown",
- "id": "eb443685",
+ "id": "146255dd",
"metadata": {},
"source": [
"```{solution-end}\n",
@@ -563,7 +553,7 @@
},
{
"cell_type": "markdown",
- "id": "3f86f0fc",
+ "id": "cac7366c",
"metadata": {},
"source": [
"When we run this we again find that mixed neighborhoods break down and segregation emerges.\n",
@@ -574,7 +564,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "6a40b10c",
+ "id": "d2fdf117",
"metadata": {},
"outputs": [],
"source": [
@@ -584,19 +574,48 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "ebb75eda",
+ "id": "88ba0e02",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.14.1"
+ }
+ },
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
- }
+ },
+ "source_map": [
+ 12,
+ 68,
+ 73,
+ 97,
+ 116,
+ 148,
+ 173,
+ 221,
+ 229,
+ 252,
+ 269,
+ 310,
+ 314,
+ 316,
+ 371,
+ 471,
+ 476,
+ 482,
+ 486
+ ]
},
"nbformat": 4,
"nbformat_minor": 5
-}
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/schelling.md b/book/_build/html/_sources/schelling.md
new file mode 100644
index 0000000..8032e10
--- /dev/null
+++ b/book/_build/html/_sources/schelling.md
@@ -0,0 +1,488 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.14.1
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+(schelling)=
+```{raw} html
+
+```
+
+# Racial Segregation
+
+```{index} single: Schelling Segregation Model
+```
+
+```{index} single: Models; Schelling's Segregation Model
+```
+
+## Outline
+
+In 1969, Thomas C. Schelling developed a simple but striking model of racial
+segregation {cite}`Schelling1969`.
+
+His model studies the dynamics of racially mixed neighborhoods.
+
+Like much of Schelling's work, the model shows how local interactions can lead
+to surprising aggregate outcomes.
+
+It studies a setting where agents (think of households) have relatively mild
+preference for neighbors of the same race.
+
+For example, these agents might be comfortable with a mixed race neighborhood
+but uncomfortable when they feel "surrounded" by people from a different race.
+
+Schelling illustrated the follow surprising result: in such a setting, mixed
+race neighborhoods are likely to be unstable, tending to collapse over time.
+
+In fact the model predicts strongly divided neighborhoods, with high levels of
+segregation.
+
+In other words, extreme segregation outcomes arise even though people's
+preferences are not particularly extreme.
+
+These extreme outcomes happen because of *interactions* between agents in the
+model (e.g., households in a city) that drive self-reinforcing dynamics in the
+model.
+
+These ideas will become clearer as the lecture unfolds.
+
+In recognition of his work on segregation and other research, Schelling was
+awarded the 2005 Nobel Prize in Economic Sciences (joint with Robert Aumann).
+
+
+Let's start with some imports:
+
+```{code-cell} ipython3
+import matplotlib.pyplot as plt
+from random import uniform, seed
+from math import sqrt
+import numpy as np
+```
+
+## The model
+
+In this section we will build a version of Schelling's model.
+
+### Set-Up
+
+We will cover a variation of Schelling's model that is different from the
+original but also easy to program and, at the same time, captures his main
+idea.
+
+Suppose we have two types of people: orange people and green people.
+
+Assume there are $n$ of each type.
+
+These agents all live on a single unit square.
+
+Thus, the location (e.g, address) of an agent is just a point $(x, y)$, where
+$0 < x, y < 1$.
+
+* The set of all points $(x,y)$ satisfying $0 < x, y < 1$ is called the **unit square**
+* Below we denote the unit square by $S$
+
++++
+
+### Preferences
+
+We will say that an agent is *happy* if 5 or more of her 10 nearest neighbors are of the same type.
+
+An agent who is not happy is called *unhappy*.
+
+For example,
+
+* if an agent is orange and 5 of her 10 nearest neighbors are orange, then she is happy.
+* if an agent is green and 8 of her 10 nearest neighbors are orange, then she is unhappy.
+
+'Nearest' is in terms of [Euclidean distance](https://en.wikipedia.org/wiki/Euclidean_distance).
+
+An important point to note is that agents are **not** averse to living in mixed areas.
+
+They are perfectly happy if half of their neighbors are of the other color.
+
++++
+
+### Behavior
+
+Initially, agents are mixed together (integrated).
+
+In particular, we assume that the initial location of each agent is an
+independent draw from a bivariate uniform distribution on the unit square $S$.
+
+* First their $x$ coordinate is drawn from a uniform distribution on $(0,1)$
+* Then, independently, their $y$ coordinate is drawn from the same distribution.
+
+Now, cycling through the set of all agents, each agent is now given the chance to stay or move.
+
+Each agent stays if they are happy and moves if they are unhappy.
+
+The algorithm for moving is as follows
+
+```{prf:algorithm} Jump Chain Algorithm
+:label: move_algo
+
+1. Draw a random location in $S$
+1. If happy at new location, move there
+1. Otherwise, go to step 1
+
+```
+
+We cycle continuously through the agents, each time allowing an unhappy agent
+to move.
+
+We continue to cycle until no one wishes to move.
+
++++
+
+## Results
+
+Let's now implement and run this simulation.
+
+In what follows, agents are modeled as [objects](https://python-programming.quantecon.org/python_oop.html).
+
+Here's an indication of their structure:
+
+```{code-block} none
+* Data:
+
+ * type (green or orange)
+ * location
+
+* Methods:
+
+ * determine whether happy or not given locations of other agents
+ * If not happy, move
+ * find a new location where happy
+```
+
+Let's build them.
+
+```{code-cell} ipython3
+class Agent:
+
+ def __init__(self, type):
+ self.type = type
+ self.draw_location()
+
+ def draw_location(self):
+ self.location = uniform(0, 1), uniform(0, 1)
+
+ def get_distance(self, other):
+ "Computes the euclidean distance between self and other agent."
+ a = (self.location[0] - other.location[0])**2
+ b = (self.location[1] - other.location[1])**2
+ return sqrt(a + b)
+
+ def happy(self,
+ agents, # List of other agents
+ num_neighbors=10, # No. of agents viewed as neighbors
+ require_same_type=5): # How many neighbors must be same type
+ """
+ True if a sufficient number of nearest neighbors are of the same
+ type.
+ """
+
+ distances = []
+
+ # Distances is a list of pairs (d, agent), where d is distance from
+ # agent to self
+ for agent in agents:
+ if self != agent:
+ distance = self.get_distance(agent)
+ distances.append((distance, agent))
+
+ # Sort from smallest to largest, according to distance
+ distances.sort()
+
+ # Extract the neighboring agents
+ neighbors = [agent for d, agent in distances[:num_neighbors]]
+
+ # Count how many neighbors have the same type as self
+ num_same_type = sum(self.type == agent.type for agent in neighbors)
+ return num_same_type >= require_same_type
+
+ def update(self, agents):
+ "If not happy, then randomly choose new locations until happy."
+ while not self.happy(agents):
+ self.draw_location()
+```
+
+Here's some code that takes a list of agents and produces a plot showing their
+locations on the unit square.
+
+Orange agents are represented by orange dots and green ones are represented by
+green dots.
+
+```{code-cell} ipython3
+def plot_distribution(agents, cycle_num):
+ "Plot the distribution of agents after cycle_num rounds of the loop."
+ x_values_0, y_values_0 = [], []
+ x_values_1, y_values_1 = [], []
+ # == Obtain locations of each type == #
+ for agent in agents:
+ x, y = agent.location
+ if agent.type == 0:
+ x_values_0.append(x)
+ y_values_0.append(y)
+ else:
+ x_values_1.append(x)
+ y_values_1.append(y)
+ fig, ax = plt.subplots()
+ plot_args = {'markersize': 8, 'alpha': 0.8}
+ ax.set_facecolor('azure')
+ ax.plot(x_values_0, y_values_0,
+ 'o', markerfacecolor='orange', **plot_args)
+ ax.plot(x_values_1, y_values_1,
+ 'o', markerfacecolor='green', **plot_args)
+ ax.set_title(f'Cycle {cycle_num-1}')
+ plt.show()
+```
+
+And here's some pseudocode for the main loop, where we cycle through the
+agents until no one wishes to move.
+
+The pseudocode is
+
+```{code-block} none
+plot the distribution
+while agents are still moving
+ for agent in agents
+ give agent the opportunity to move
+plot the distribution
+```
+
+The real code is below
+
+```{code-cell} ipython3
+def run_simulation(num_of_type_0=600,
+ num_of_type_1=600,
+ max_iter=100_000, # Maximum number of iterations
+ set_seed=1234):
+
+ # Set the seed for reproducibility
+ seed(set_seed)
+
+ # Create a list of agents of type 0
+ agents = [Agent(0) for i in range(num_of_type_0)]
+ # Append a list of agents of type 1
+ agents.extend(Agent(1) for i in range(num_of_type_1))
+
+ # Initialize a counter
+ count = 1
+
+ # Plot the initial distribution
+ plot_distribution(agents, count)
+
+ # Loop until no agent wishes to move
+ while count < max_iter:
+ print('Entering loop ', count)
+ count += 1
+ no_one_moved = True
+ for agent in agents:
+ old_location = agent.location
+ agent.update(agents)
+ if agent.location != old_location:
+ no_one_moved = False
+ if no_one_moved:
+ break
+
+ # Plot final distribution
+ plot_distribution(agents, count)
+
+ if count < max_iter:
+ print(f'Converged after {count} iterations.')
+ else:
+ print('Hit iteration bound and terminated.')
+
+```
+
+Let's have a look at the results.
+
+```{code-cell} ipython3
+run_simulation()
+```
+
+As discussed above, agents are initially mixed randomly together.
+
+But after several cycles, they become segregated into distinct regions.
+
+In this instance, the program terminated after a small number of cycles
+through the set of agents, indicating that all agents had reached a state of
+happiness.
+
+What is striking about the pictures is how rapidly racial integration breaks down.
+
+This is despite the fact that people in the model don't actually mind living mixed with the other type.
+
+Even with these preferences, the outcome is a high degree of segregation.
+
+
+
+## Exercises
+
+```{exercise-start}
+:label: schelling_ex1
+```
+
+The object oriented style that we used for coding above is neat but harder to
+optimize than procedural code (i.e., code based around functions rather than
+objects and methods).
+
+Try writing a new version of the model that stores
+
+* the locations of all agents as a 2D NumPy array of floats.
+* the types of all agents as a flat NumPy array of integers.
+
+Write functions that act on this data to update the model using the logic
+similar to that described above.
+
+However, implement the following two changes:
+
+1. Agents are offered a move at random (i.e., selected randomly and given the
+ opportunity to move).
+2. After an agent has moved, flip their type with probability 0.01
+
+The second change introduces extra randomness into the model.
+
+(We can imagine that, every so often, an agent moves to a different city and,
+with small probability, is replaced by an agent of the other type.)
+
+```{exercise-end}
+```
+
+```{solution-start} schelling_ex1
+:class: dropdown
+```
+solution here
+
+```{code-cell} ipython3
+from numpy.random import uniform, randint
+
+n = 1000 # number of agents (agents = 0, ..., n-1)
+k = 10 # number of agents regarded as neighbors
+require_same_type = 5 # want >= require_same_type neighbors of the same type
+
+def initialize_state():
+ locations = uniform(size=(n, 2))
+ types = randint(0, high=2, size=n) # label zero or one
+ return locations, types
+
+
+def compute_distances_from_loc(loc, locations):
+ """ Compute distance from location loc to all other points. """
+ return np.linalg.norm(loc - locations, axis=1)
+
+def get_neighbors(loc, locations):
+ " Get all neighbors of a given location. "
+ all_distances = compute_distances_from_loc(loc, locations)
+ indices = np.argsort(all_distances) # sort agents by distance to loc
+ neighbors = indices[:k] # keep the k closest ones
+ return neighbors
+
+def is_happy(i, locations, types):
+ happy = True
+ agent_loc = locations[i, :]
+ agent_type = types[i]
+ neighbors = get_neighbors(agent_loc, locations)
+ neighbor_types = types[neighbors]
+ if sum(neighbor_types == agent_type) < require_same_type:
+ happy = False
+ return happy
+
+def count_happy(locations, types):
+ " Count the number of happy agents. "
+ happy_sum = 0
+ for i in range(n):
+ happy_sum += is_happy(i, locations, types)
+ return happy_sum
+
+def update_agent(i, locations, types):
+ " Move agent if unhappy. "
+ moved = False
+ while not is_happy(i, locations, types):
+ moved = True
+ locations[i, :] = uniform(), uniform()
+ return moved
+
+def plot_distribution(locations, types, title, savepdf=False):
+ " Plot the distribution of agents after cycle_num rounds of the loop."
+ fig, ax = plt.subplots()
+ colors = 'orange', 'green'
+ for agent_type, color in zip((0, 1), colors):
+ idx = (types == agent_type)
+ ax.plot(locations[idx, 0],
+ locations[idx, 1],
+ 'o',
+ markersize=8,
+ markerfacecolor=color,
+ alpha=0.8)
+ ax.set_title(title)
+ plt.show()
+
+def sim_random_select(max_iter=100_000, flip_prob=0.01, test_freq=10_000):
+ """
+ Simulate by randomly selecting one household at each update.
+
+ Flip the color of the household with probability `flip_prob`.
+
+ """
+
+ locations, types = initialize_state()
+ current_iter = 0
+
+ while current_iter <= max_iter:
+
+ # Choose a random agent and update them
+ i = randint(0, n)
+ moved = update_agent(i, locations, types)
+
+ if flip_prob > 0:
+ # flip agent i's type with probability epsilon
+ U = uniform()
+ if U < flip_prob:
+ current_type = types[i]
+ types[i] = 0 if current_type == 1 else 1
+
+ # Every so many updates, plot and test for convergence
+ if current_iter % test_freq == 0:
+ cycle = current_iter / n
+ plot_distribution(locations, types, f'iteration {current_iter}')
+ if count_happy(locations, types) == n:
+ print(f"Converged at iteration {current_iter}")
+ break
+
+ current_iter += 1
+
+ if current_iter > max_iter:
+ print(f"Terminating at iteration {current_iter}")
+```
+
+```{solution-end}
+```
+
++++
+
+When we run this we again find that mixed neighborhoods break down and segregation emerges.
+
+Here's a sample run.
+
+```{code-cell} ipython3
+sim_random_select(max_iter=50_000, flip_prob=0.01, test_freq=10_000)
+```
+
+```{code-cell} ipython3
+
+```
diff --git a/content/lectures/short_path.ipynb b/book/_build/html/_sources/short_path.ipynb
similarity index 93%
rename from content/lectures/short_path.ipynb
rename to book/_build/html/_sources/short_path.ipynb
index 98d791f..1b029cc 100644
--- a/content/lectures/short_path.ipynb
+++ b/book/_build/html/_sources/short_path.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "9156396f",
+ "id": "cd30f18a",
"metadata": {},
"source": [
"(short_path)=\n",
@@ -19,10 +19,6 @@
"```{index} single: Dynamic Programming; Shortest Paths\n",
"```\n",
"\n",
- "```{contents} Contents\n",
- ":depth: 2\n",
- "```\n",
- "\n",
"## Overview\n",
"\n",
"The shortest path problem is a [classic problem](https://en.wikipedia.org/wiki/Shortest_path) in mathematics and computer science with applications in\n",
@@ -48,7 +44,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "b8fb1690",
+ "id": "0496fef5",
"metadata": {},
"outputs": [],
"source": [
@@ -57,10 +53,10 @@
},
{
"cell_type": "markdown",
- "id": "441c5fd7",
+ "id": "c75fe860",
"metadata": {},
"source": [
- "## Outline of the Problem\n",
+ "## Outline of the problem\n",
"\n",
"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.\n",
"\n",
@@ -81,7 +77,7 @@
"\n",
"* Minimum cost for supplier to reach a destination.\n",
"* Routing of packets on the internet (minimize time).\n",
- "* Etc., etc.\n",
+ "* etc., etc.\n",
"\n",
"For this simple graph, a quick scan of the edges shows that the optimal paths are\n",
"\n",
@@ -97,13 +93,13 @@
"\n",
"```\n",
"\n",
- "## Finding Least-Cost Paths\n",
+ "## Finding least-cost paths\n",
"\n",
"For large graphs, we need a systematic solution.\n",
"\n",
"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.\n",
"\n",
- "Suppose that we know $J(v)$ for each node $v$, as shown below for the graph from the preceding example\n",
+ "Suppose that we know $J(v)$ for each node $v$, as shown below for the graph from the preceding example.\n",
"\n",
"```{figure} /_static/lecture_specific/short_path/graph2.png\n",
"\n",
@@ -140,19 +136,19 @@
"J(v) = \\min_{w \\in F_v} \\{ c(v, w) + J(w) \\}\n",
"```\n",
"\n",
- "This is known as the *Bellman equation*, after the mathematician Richard Bellman.\n",
+ "This is known as the **Bellman equation**, after the mathematician [Richard Bellman](https://en.wikipedia.org/wiki/Richard_E._Bellman).\n",
"\n",
"The Bellman equation can be thought of as a restriction that $J$ must\n",
"satisfy.\n",
"\n",
"What we want to do now is use this restriction to compute $J$.\n",
"\n",
- "## Solving for Minimum Cost-to-Go\n",
+ "## Solving for minimum cost-to-go\n",
"\n",
"Let's look at an algorithm for computing $J$ and then think about how to\n",
"implement it.\n",
"\n",
- "### The Algorithm\n",
+ "### The algorithm\n",
"\n",
"The standard algorithm for finding $J$ is to start an initial guess and then iterate.\n",
"\n",
@@ -211,7 +207,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "2661fc5b",
+ "id": "08dd4541",
"metadata": {},
"outputs": [],
"source": [
@@ -228,12 +224,12 @@
},
{
"cell_type": "markdown",
- "id": "9fb4ad16",
+ "id": "48a6eba9",
"metadata": {},
"source": [
"Notice that the cost of staying still (on the principle diagonal) is set to\n",
"\n",
- "* np.inf for non-destination nodes --- moving on is required.\n",
+ "* `np.inf` for non-destination nodes --- moving on is required.\n",
"* 0 for the destination node --- here is where we stop.\n",
"\n",
"For the sequence of approximations $\\{J_n\\}$ of the cost-to-go functions, we can use NumPy arrays.\n",
@@ -244,7 +240,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "dfeebde2",
+ "id": "8a1c526b",
"metadata": {},
"outputs": [],
"source": [
@@ -257,25 +253,21 @@
"\n",
"while i < max_iter:\n",
" for v in nodes:\n",
- " # minimize Q[v, w] + J[w] over all choices of w\n",
- " lowest_cost = inf\n",
- " for w in nodes:\n",
- " cost = Q[v, w] + J[w]\n",
- " if cost < lowest_cost:\n",
- " lowest_cost = cost\n",
- " next_J[v] = lowest_cost\n",
- " if np.equal(next_J, J).all():\n",
+ " # Minimize Q[v, w] + J[w] over all choices of w\n",
+ " next_J[v] = np.min(Q[v, :] + J)\n",
+ " \n",
+ " if np.array_equal(next_J, J): \n",
" break\n",
- " else:\n",
- " J[:] = next_J # Copy contents of next_J to J\n",
- " i += 1\n",
+ " \n",
+ " J[:] = next_J # Copy contents of next_J to J\n",
+ " i += 1\n",
"\n",
"print(\"The cost-to-go function is\", J)"
]
},
{
"cell_type": "markdown",
- "id": "5ba658bb",
+ "id": "46a33c27",
"metadata": {},
"source": [
"This matches with the numbers we obtained by inspection above.\n",
@@ -312,7 +304,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "5c7af7f5",
+ "id": "3ae4e525",
"metadata": {},
"outputs": [],
"source": [
@@ -421,7 +413,7 @@
},
{
"cell_type": "markdown",
- "id": "7cda6c24",
+ "id": "2cbd502a",
"metadata": {},
"source": [
"```{exercise-end}\n",
@@ -437,7 +429,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "81d7f3e5",
+ "id": "39712dd1",
"metadata": {},
"outputs": [],
"source": [
@@ -466,7 +458,7 @@
},
{
"cell_type": "markdown",
- "id": "b820d74a",
+ "id": "1c038572",
"metadata": {},
"source": [
"In addition, let's write\n",
@@ -482,16 +474,12 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "c7102951",
+ "id": "6134ca95",
"metadata": {},
"outputs": [],
"source": [
"def bellman(J, Q):\n",
- " num_nodes = Q.shape[0]\n",
- " next_J = np.empty_like(J)\n",
- " for v in range(num_nodes):\n",
- " next_J[v] = np.min(Q[v, :] + J)\n",
- " return next_J\n",
+ " return np.min(Q + J, axis=1)\n",
"\n",
"\n",
"def compute_cost_to_go(Q):\n",
@@ -513,7 +501,7 @@
},
{
"cell_type": "markdown",
- "id": "330ca8e1",
+ "id": "0d15e800",
"metadata": {},
"source": [
"We used np.allclose() rather than testing exact equality because we are\n",
@@ -526,7 +514,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "8368151d",
+ "id": "b97b41b4",
"metadata": {},
"outputs": [],
"source": [
@@ -546,7 +534,7 @@
},
{
"cell_type": "markdown",
- "id": "dba50533",
+ "id": "56ad5a8f",
"metadata": {},
"source": [
"Okay, now we have the necessary functions, let's call them to do the job we were assigned."
@@ -555,7 +543,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "ca8cec8c",
+ "id": "57a6b0cc",
"metadata": {},
"outputs": [],
"source": [
@@ -566,7 +554,7 @@
},
{
"cell_type": "markdown",
- "id": "0d5334a1",
+ "id": "1e8eb877",
"metadata": {},
"source": [
"The total cost of the path should agree with $J[0]$ so let's check this."
@@ -575,7 +563,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "eb56ba97",
+ "id": "e630d945",
"metadata": {},
"outputs": [],
"source": [
@@ -584,7 +572,7 @@
},
{
"cell_type": "markdown",
- "id": "0f94a3ef",
+ "id": "e0cfce96",
"metadata": {},
"source": [
"```{solution-end}\n",
@@ -593,12 +581,39 @@
}
],
"metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst"
+ }
+ },
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
- }
+ },
+ "source_map": [
+ 10,
+ 47,
+ 49,
+ 198,
+ 208,
+ 219,
+ 239,
+ 271,
+ 373,
+ 384,
+ 406,
+ 417,
+ 437,
+ 445,
+ 458,
+ 462,
+ 466,
+ 470,
+ 472
+ ]
},
"nbformat": 4,
"nbformat_minor": 5
-}
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/short_path.md b/book/_build/html/_sources/short_path.md
new file mode 100644
index 0000000..ce547ef
--- /dev/null
+++ b/book/_build/html/_sources/short_path.md
@@ -0,0 +1,475 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+kernelspec:
+ display_name: Python 3
+ language: python
+ name: python3
+---
+
+(short_path)=
+```{raw} html
+
+```
+
+# Shortest Paths
+
+```{index} single: Dynamic Programming; Shortest Paths
+```
+
+## Overview
+
+The shortest path problem is a [classic problem](https://en.wikipedia.org/wiki/Shortest_path) in mathematics and computer science with applications in
+
+* Economics (sequential decision making, analysis of social networks, etc.)
+* Operations research and transportation
+* Robotics and artificial intelligence
+* Telecommunication network design and routing
+* etc., etc.
+
+Variations of the methods we discuss in this lecture are used millions of times every day, in applications such as
+
+* Google Maps
+* routing packets on the internet
+
+For us, the shortest path problem also provides a nice introduction to the logic of **dynamic programming**.
+
+Dynamic programming is an extremely powerful optimization technique that we apply in many lectures on this site.
+
+The only scientific library we'll need in what follows is NumPy:
+
+```{code-cell} python3
+import numpy as np
+```
+
+## Outline of the problem
+
+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.
+
+Consider the following graph
+
+```{figure} /_static/lecture_specific/short_path/graph.png
+
+```
+
+We wish to travel from node (vertex) A to node G at minimum cost
+
+* Arrows (edges) indicate the movements we can take.
+* Numbers on edges indicate the cost of traveling that edge.
+
+(Graphs such as the one above are called weighted [directed graphs](https://en.wikipedia.org/wiki/Directed_graph).)
+
+Possible interpretations of the graph include
+
+* Minimum cost for supplier to reach a destination.
+* Routing of packets on the internet (minimize time).
+* etc., etc.
+
+For this simple graph, a quick scan of the edges shows that the optimal paths are
+
+* A, C, F, G at cost 8
+
+```{figure} /_static/lecture_specific/short_path/graph4.png
+
+```
+
+* A, D, F, G at cost 8
+
+```{figure} /_static/lecture_specific/short_path/graph3.png
+
+```
+
+## Finding least-cost paths
+
+For large graphs, we need a systematic solution.
+
+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.
+
+Suppose that we know $J(v)$ for each node $v$, as shown below for the graph from the preceding example.
+
+```{figure} /_static/lecture_specific/short_path/graph2.png
+
+```
+
+Note that $J(G) = 0$.
+
+The best path can now be found as follows
+
+1. Start at node $v = A$
+1. From current node $v$, move to any node that solves
+
+```{math}
+:label: spprebell
+
+\min_{w \in F_v} \{ c(v, w) + J(w) \}
+```
+
+where
+
+* $F_v$ is the set of nodes that can be reached from $v$ in one step.
+* $c(v, w)$ is the cost of traveling from $v$ to $w$.
+
+Hence, if we know the function $J$, then finding the best path is almost trivial.
+
+But how can we find the cost-to-go function $J$?
+
+Some thought will convince you that, for every node $v$,
+the function $J$ satisfies
+
+```{math}
+:label: spbell
+
+J(v) = \min_{w \in F_v} \{ c(v, w) + J(w) \}
+```
+
+This is known as the **Bellman equation**, after the mathematician [Richard Bellman](https://en.wikipedia.org/wiki/Richard_E._Bellman).
+
+The Bellman equation can be thought of as a restriction that $J$ must
+satisfy.
+
+What we want to do now is use this restriction to compute $J$.
+
+## Solving for minimum cost-to-go
+
+Let's look at an algorithm for computing $J$ and then think about how to
+implement it.
+
+### The algorithm
+
+The standard algorithm for finding $J$ is to start an initial guess and then iterate.
+
+This is a standard approach to solving nonlinear equations, often called
+the method of **successive approximations**.
+
+Our initial guess will be
+
+```{math}
+:label: spguess
+
+J_0(v) = 0 \text{ for all } v
+```
+
+Now
+
+1. Set $n = 0$
+1. Set $J_{n+1} (v) = \min_{w \in F_v} \{ c(v, w) + J_n(w) \}$ for all $v$
+1. If $J_{n+1}$ and $J_n$ are not equal then increment $n$, go to 2
+
+This sequence converges to $J$.
+
+Although we omit the proof, we'll prove similar claims in our other lectures
+on dynamic programming.
+
+### Implementation
+
+Having an algorithm is a good start, but we also need to think about how to
+implement it on a computer.
+
+First, for the cost function $c$, we'll implement it as a matrix
+$Q$, where a typical element is
+
+$$
+Q(v, w)
+=
+\begin{cases}
+ & c(v, w) \text{ if } w \in F_v \\
+ & +\infty \text{ otherwise }
+\end{cases}
+$$
+
+In this context $Q$ is usually called the **distance matrix**.
+
+We're also numbering the nodes now, with $A = 0$, so, for example
+
+$$
+Q(1, 2)
+=
+\text{ the cost of traveling from B to C }
+$$
+
+For example, for the simple graph above, we set
+
+```{code-cell} python3
+from numpy import inf
+
+Q = np.array([[inf, 1, 5, 3, inf, inf, inf],
+ [inf, inf, inf, 9, 6, inf, inf],
+ [inf, inf, inf, inf, inf, 2, inf],
+ [inf, inf, inf, inf, inf, 4, 8],
+ [inf, inf, inf, inf, inf, inf, 4],
+ [inf, inf, inf, inf, inf, inf, 1],
+ [inf, inf, inf, inf, inf, inf, 0]])
+```
+
+Notice that the cost of staying still (on the principle diagonal) is set to
+
+* `np.inf` for non-destination nodes --- moving on is required.
+* 0 for the destination node --- here is where we stop.
+
+For the sequence of approximations $\{J_n\}$ of the cost-to-go functions, we can use NumPy arrays.
+
+Let's try with this example and see how we go:
+
+```{code-cell} python3
+nodes = range(7) # Nodes = 0, 1, ..., 6
+J = np.zeros_like(nodes, dtype=int) # Initial guess
+next_J = np.empty_like(nodes, dtype=int) # Stores updated guess
+
+max_iter = 500
+i = 0
+
+while i < max_iter:
+ for v in nodes:
+ # Minimize Q[v, w] + J[w] over all choices of w
+ next_J[v] = np.min(Q[v, :] + J)
+
+ if np.array_equal(next_J, J):
+ break
+
+ J[:] = next_J # Copy contents of next_J to J
+ i += 1
+
+print("The cost-to-go function is", J)
+```
+
+This matches with the numbers we obtained by inspection above.
+
+But, importantly, we now have a methodology for tackling large graphs.
+
+## Exercises
+
+
+```{exercise-start}
+:label: short_path_ex1
+```
+
+The text below describes a weighted directed graph.
+
+The line `node0, node1 0.04, node8 11.11, node14 72.21` means that from node0 we can go to
+
+* node1 at cost 0.04
+* node8 at cost 11.11
+* node14 at cost 72.21
+
+No other nodes can be reached directly from node0.
+
+Other lines have a similar interpretation.
+
+Your task is to use the algorithm given above to find the optimal path and its cost.
+
+```{note}
+You will be dealing with floating point numbers now, rather than
+integers, so consider replacing `np.equal()` with `np.allclose()`.
+```
+
+```{code-cell} python3
+%%file graph.txt
+node0, node1 0.04, node8 11.11, node14 72.21
+node1, node46 1247.25, node6 20.59, node13 64.94
+node2, node66 54.18, node31 166.80, node45 1561.45
+node3, node20 133.65, node6 2.06, node11 42.43
+node4, node75 3706.67, node5 0.73, node7 1.02
+node5, node45 1382.97, node7 3.33, node11 34.54
+node6, node31 63.17, node9 0.72, node10 13.10
+node7, node50 478.14, node9 3.15, node10 5.85
+node8, node69 577.91, node11 7.45, node12 3.18
+node9, node70 2454.28, node13 4.42, node20 16.53
+node10, node89 5352.79, node12 1.87, node16 25.16
+node11, node94 4961.32, node18 37.55, node20 65.08
+node12, node84 3914.62, node24 34.32, node28 170.04
+node13, node60 2135.95, node38 236.33, node40 475.33
+node14, node67 1878.96, node16 2.70, node24 38.65
+node15, node91 3597.11, node17 1.01, node18 2.57
+node16, node36 392.92, node19 3.49, node38 278.71
+node17, node76 783.29, node22 24.78, node23 26.45
+node18, node91 3363.17, node23 16.23, node28 55.84
+node19, node26 20.09, node20 0.24, node28 70.54
+node20, node98 3523.33, node24 9.81, node33 145.80
+node21, node56 626.04, node28 36.65, node31 27.06
+node22, node72 1447.22, node39 136.32, node40 124.22
+node23, node52 336.73, node26 2.66, node33 22.37
+node24, node66 875.19, node26 1.80, node28 14.25
+node25, node70 1343.63, node32 36.58, node35 45.55
+node26, node47 135.78, node27 0.01, node42 122.00
+node27, node65 480.55, node35 48.10, node43 246.24
+node28, node82 2538.18, node34 21.79, node36 15.52
+node29, node64 635.52, node32 4.22, node33 12.61
+node30, node98 2616.03, node33 5.61, node35 13.95
+node31, node98 3350.98, node36 20.44, node44 125.88
+node32, node97 2613.92, node34 3.33, node35 1.46
+node33, node81 1854.73, node41 3.23, node47 111.54
+node34, node73 1075.38, node42 51.52, node48 129.45
+node35, node52 17.57, node41 2.09, node50 78.81
+node36, node71 1171.60, node54 101.08, node57 260.46
+node37, node75 269.97, node38 0.36, node46 80.49
+node38, node93 2767.85, node40 1.79, node42 8.78
+node39, node50 39.88, node40 0.95, node41 1.34
+node40, node75 548.68, node47 28.57, node54 53.46
+node41, node53 18.23, node46 0.28, node54 162.24
+node42, node59 141.86, node47 10.08, node72 437.49
+node43, node98 2984.83, node54 95.06, node60 116.23
+node44, node91 807.39, node46 1.56, node47 2.14
+node45, node58 79.93, node47 3.68, node49 15.51
+node46, node52 22.68, node57 27.50, node67 65.48
+node47, node50 2.82, node56 49.31, node61 172.64
+node48, node99 2564.12, node59 34.52, node60 66.44
+node49, node78 53.79, node50 0.51, node56 10.89
+node50, node85 251.76, node53 1.38, node55 20.10
+node51, node98 2110.67, node59 23.67, node60 73.79
+node52, node94 1471.80, node64 102.41, node66 123.03
+node53, node72 22.85, node56 4.33, node67 88.35
+node54, node88 967.59, node59 24.30, node73 238.61
+node55, node84 86.09, node57 2.13, node64 60.80
+node56, node76 197.03, node57 0.02, node61 11.06
+node57, node86 701.09, node58 0.46, node60 7.01
+node58, node83 556.70, node64 29.85, node65 34.32
+node59, node90 820.66, node60 0.72, node71 0.67
+node60, node76 48.03, node65 4.76, node67 1.63
+node61, node98 1057.59, node63 0.95, node64 4.88
+node62, node91 132.23, node64 2.94, node76 38.43
+node63, node66 4.43, node72 70.08, node75 56.34
+node64, node80 47.73, node65 0.30, node76 11.98
+node65, node94 594.93, node66 0.64, node73 33.23
+node66, node98 395.63, node68 2.66, node73 37.53
+node67, node82 153.53, node68 0.09, node70 0.98
+node68, node94 232.10, node70 3.35, node71 1.66
+node69, node99 247.80, node70 0.06, node73 8.99
+node70, node76 27.18, node72 1.50, node73 8.37
+node71, node89 104.50, node74 8.86, node91 284.64
+node72, node76 15.32, node84 102.77, node92 133.06
+node73, node83 52.22, node76 1.40, node90 243.00
+node74, node81 1.07, node76 0.52, node78 8.08
+node75, node92 68.53, node76 0.81, node77 1.19
+node76, node85 13.18, node77 0.45, node78 2.36
+node77, node80 8.94, node78 0.98, node86 64.32
+node78, node98 355.90, node81 2.59
+node79, node81 0.09, node85 1.45, node91 22.35
+node80, node92 121.87, node88 28.78, node98 264.34
+node81, node94 99.78, node89 39.52, node92 99.89
+node82, node91 47.44, node88 28.05, node93 11.99
+node83, node94 114.95, node86 8.75, node88 5.78
+node84, node89 19.14, node94 30.41, node98 121.05
+node85, node97 94.51, node87 2.66, node89 4.90
+node86, node97 85.09
+node87, node88 0.21, node91 11.14, node92 21.23
+node88, node93 1.31, node91 6.83, node98 6.12
+node89, node97 36.97, node99 82.12
+node90, node96 23.53, node94 10.47, node99 50.99
+node91, node97 22.17
+node92, node96 10.83, node97 11.24, node99 34.68
+node93, node94 0.19, node97 6.71, node99 32.77
+node94, node98 5.91, node96 2.03
+node95, node98 6.17, node99 0.27
+node96, node98 3.32, node97 0.43, node99 5.87
+node97, node98 0.30
+node98, node99 0.33
+node99,
+```
+
+```{exercise-end}
+```
+
+```{solution-start} short_path_ex1
+:class: dropdown
+```
+
+First let's write a function that reads in the graph data above and builds a distance matrix.
+
+```{code-cell} python3
+num_nodes = 100
+destination_node = 99
+
+def map_graph_to_distance_matrix(in_file):
+
+ # First let's set of the distance matrix Q with inf everywhere
+ Q = np.full((num_nodes, num_nodes), np.inf)
+
+ # Now we read in the data and modify Q
+ with open(in_file) as infile:
+ for line in infile:
+ elements = line.split(',')
+ node = elements.pop(0)
+ node = int(node[4:]) # convert node description to integer
+ if node != destination_node:
+ for element in elements:
+ destination, cost = element.split()
+ destination = int(destination[4:])
+ Q[node, destination] = float(cost)
+ Q[destination_node, destination_node] = 0
+ return Q
+```
+
+In addition, let's write
+
+1. a "Bellman operator" function that takes a distance matrix and current guess of J and returns an updated guess of J, and
+1. a function that takes a distance matrix and returns a cost-to-go function.
+
+We'll use the algorithm described above.
+
+The minimization step is vectorized to make it faster.
+
+```{code-cell} python3
+def bellman(J, Q):
+ return np.min(Q + J, axis=1)
+
+
+def compute_cost_to_go(Q):
+ num_nodes = Q.shape[0]
+ J = np.zeros(num_nodes) # Initial guess
+ max_iter = 500
+ i = 0
+
+ while i < max_iter:
+ next_J = bellman(J, Q)
+ if np.allclose(next_J, J):
+ break
+ else:
+ J[:] = next_J # Copy contents of next_J to J
+ i += 1
+
+ return(J)
+```
+
+We used np.allclose() rather than testing exact equality because we are
+dealing with floating point numbers now.
+
+Finally, here's a function that uses the cost-to-go function to obtain the
+optimal path (and its cost).
+
+```{code-cell} python3
+def print_best_path(J, Q):
+ sum_costs = 0
+ current_node = 0
+ while current_node != destination_node:
+ print(current_node)
+ # Move to the next node and increment costs
+ next_node = np.argmin(Q[current_node, :] + J)
+ sum_costs += Q[current_node, next_node]
+ current_node = next_node
+
+ print(destination_node)
+ print('Cost: ', sum_costs)
+```
+
+Okay, now we have the necessary functions, let's call them to do the job we were assigned.
+
+```{code-cell} python3
+Q = map_graph_to_distance_matrix('graph.txt')
+J = compute_cost_to_go(Q)
+print_best_path(J, Q)
+```
+
+The total cost of the path should agree with $J[0]$ so let's check this.
+
+```{code-cell} python3
+J[0]
+```
+
+```{solution-end}
+```
\ No newline at end of file
diff --git a/content/lectures/simple_linear_regression.ipynb b/book/_build/html/_sources/simple_linear_regression.ipynb
similarity index 76%
rename from content/lectures/simple_linear_regression.ipynb
rename to book/_build/html/_sources/simple_linear_regression.ipynb
index 3404edf..d60ff08 100644
--- a/content/lectures/simple_linear_regression.ipynb
+++ b/book/_build/html/_sources/simple_linear_regression.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "42f9b4c0",
+ "id": "22a5ab66",
"metadata": {},
"source": [
"# Simple Linear Regression Model"
@@ -11,7 +11,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "5064b6e7",
+ "id": "64ad22f1",
"metadata": {},
"outputs": [],
"source": [
@@ -22,7 +22,7 @@
},
{
"cell_type": "markdown",
- "id": "01f8eed6",
+ "id": "5def18fc",
"metadata": {},
"source": [
"The simple regression model estimates the relationship between two variables $x_i$ and $y_i$\n",
@@ -56,7 +56,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "ad04aaa8",
+ "id": "fe268a5e",
"metadata": {},
"outputs": [],
"source": [
@@ -69,7 +69,7 @@
},
{
"cell_type": "markdown",
- "id": "35f26989",
+ "id": "f616806d",
"metadata": {},
"source": [
"We can use a scatter plot of the data to see the relationship between $y_i$ (ice-cream sales in dollars (\\$\\'s)) and $x_i$ (degrees Celsius)."
@@ -78,22 +78,29 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "b0b7d317",
- "metadata": {},
+ "id": "3278055c",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Scatter plot",
+ "name": "sales-v-temp1"
+ }
+ }
+ },
"outputs": [],
"source": [
"ax = df.plot(\n",
" x='X', \n",
" y='Y', \n",
" kind='scatter', \n",
- " ylabel='Ice-Cream Sales ($\\'s)', \n",
- " xlabel='Degrees Celcius'\n",
+ " ylabel='Ice-cream sales ($\\'s)', \n",
+ " xlabel='Degrees celcius'\n",
")"
]
},
{
"cell_type": "markdown",
- "id": "88f323c0",
+ "id": "80f15333",
"metadata": {},
"source": [
"as you can see the data suggests that more ice-cream is typically sold on hotter days. \n",
@@ -110,7 +117,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "09b9612a",
+ "id": "12d4645d",
"metadata": {},
"outputs": [],
"source": [
@@ -122,18 +129,26 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "f4dd5e1d",
- "metadata": {},
+ "id": "7b173c15",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Scatter plot with a line of fit",
+ "name": "sales-v-temp2"
+ }
+ }
+ },
"outputs": [],
"source": [
"fig, ax = plt.subplots()\n",
- "df.plot(x='X',y='Y', kind='scatter', ax=ax)\n",
- "df.plot(x='X',y='Y_hat', kind='line', ax=ax)"
+ "ax = df.plot(x='X',y='Y', kind='scatter', ax=ax)\n",
+ "ax = df.plot(x='X',y='Y_hat', kind='line', ax=ax)\n",
+ "plt.show()"
]
},
{
"cell_type": "markdown",
- "id": "9e22412f",
+ "id": "f28222f7",
"metadata": {},
"source": [
"We can see that this model does a poor job of estimating the relationship.\n",
@@ -144,7 +159,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "5c4d3677",
+ "id": "b589a51f",
"metadata": {},
"outputs": [],
"source": [
@@ -155,19 +170,27 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "abcc5425",
- "metadata": {},
+ "id": "37e62d3e",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Scatter plot with a line of fit #2",
+ "name": "sales-v-temp3"
+ }
+ }
+ },
"outputs": [],
"source": [
"fig, ax = plt.subplots()\n",
- "df.plot(x='X',y='Y', kind='scatter', ax=ax)\n",
- "df.plot(x='X',y='Y_hat', kind='line', ax=ax)"
+ "ax = df.plot(x='X',y='Y', kind='scatter', ax=ax)\n",
+ "ax = df.plot(x='X',y='Y_hat', kind='line', ax=ax)\n",
+ "plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "41ef80a6",
+ "id": "e137e489",
"metadata": {},
"outputs": [],
"source": [
@@ -178,21 +201,29 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "2644963d",
- "metadata": {},
+ "id": "fee3a55d",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Scatter plot with a line of fit #3",
+ "name": "sales-v-temp4"
+ }
+ }
+ },
"outputs": [],
"source": [
"fig, ax = plt.subplots()\n",
- "df.plot(x='X',y='Y', kind='scatter', ax=ax)\n",
- "df.plot(x='X',y='Y_hat', kind='line', ax=ax, color='g')"
+ "ax = df.plot(x='X',y='Y', kind='scatter', ax=ax)\n",
+ "ax = df.plot(x='X',y='Y_hat', kind='line', ax=ax, color='g')\n",
+ "plt.show()"
]
},
{
"cell_type": "markdown",
- "id": "2b098af9",
+ "id": "7ebfb1b3",
"metadata": {},
"source": [
- "However we need to think about formalising this guessing process by thinking of this problem as an optimization problem. \n",
+ "However we need to think about formalizing this guessing process by thinking of this problem as an optimization problem. \n",
"\n",
"Let's consider the error $\\epsilon_i$ and define the difference between the observed values $y_i$ and the estimated values $\\hat{y}_i$ which we will call the residuals\n",
"\n",
@@ -207,7 +238,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "78962405",
+ "id": "8e83a2c8",
"metadata": {},
"outputs": [],
"source": [
@@ -217,7 +248,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "40de595c",
+ "id": "01a93f4e",
"metadata": {},
"outputs": [],
"source": [
@@ -227,22 +258,30 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "858244d1",
- "metadata": {},
+ "id": "bb65e0e3",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Plot of the residuals",
+ "name": "plt-residuals"
+ }
+ }
+ },
"outputs": [],
"source": [
"fig, ax = plt.subplots()\n",
- "df.plot(x='X',y='Y', kind='scatter', ax=ax)\n",
- "df.plot(x='X',y='Y_hat', kind='line', ax=ax, color='g')\n",
- "plt.vlines(df['X'], df['Y_hat'], df['Y'], color='r');"
+ "ax = df.plot(x='X',y='Y', kind='scatter', ax=ax)\n",
+ "ax = df.plot(x='X',y='Y_hat', kind='line', ax=ax, color='g')\n",
+ "plt.vlines(df['X'], df['Y_hat'], df['Y'], color='r')\n",
+ "plt.show()"
]
},
{
"cell_type": "markdown",
- "id": "2db7b9a5",
+ "id": "61903bf2",
"metadata": {},
"source": [
- "The Ordinary Least Squares (OLS) method, as the name suggests, chooses $\\alpha$ and $\\beta$ in such a way that **minimises** the Sum of the Squared Residuals (SSR). \n",
+ "The Ordinary Least Squares (OLS) method chooses $\\alpha$ and $\\beta$ in such a way that **minimizes** the sum of the squared residuals (SSR). \n",
"\n",
"$$\n",
"\\min_{\\alpha,\\beta} \\sum_{i=1}^{N}{\\hat{e}_i^2} = \\min_{\\alpha,\\beta} \\sum_{i=1}^{N}{(y_i - \\alpha - \\beta x_i)^2}\n",
@@ -254,7 +293,7 @@
"C = \\sum_{i=1}^{N}{(y_i - \\alpha - \\beta x_i)^2}\n",
"$$\n",
"\n",
- "that we would like to minimise with parameters $\\alpha$ and $\\beta$.\n",
+ "that we would like to minimize with parameters $\\alpha$ and $\\beta$.\n",
"\n",
"## How does error change with respect to $\\alpha$ and $\\beta$\n",
"\n",
@@ -266,7 +305,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "37e6df1b",
+ "id": "5db5d677",
"metadata": {},
"outputs": [],
"source": [
@@ -276,7 +315,7 @@
},
{
"cell_type": "markdown",
- "id": "e4336dba",
+ "id": "b33122a8",
"metadata": {},
"source": [
"We can then calculate the error for a range of $\\beta$ values"
@@ -285,7 +324,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "b9b703e9",
+ "id": "e3a10384",
"metadata": {},
"outputs": [],
"source": [
@@ -296,17 +335,24 @@
},
{
"cell_type": "markdown",
- "id": "b69659aa",
+ "id": "c08f3d06",
"metadata": {},
"source": [
- "Ploting the error"
+ "Plotting the error"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "28d48003",
- "metadata": {},
+ "id": "95b9b40d",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Plotting the error",
+ "name": "plt-errors"
+ }
+ }
+ },
"outputs": [],
"source": [
"ax = pd.Series(errors).plot(xlabel='β', ylabel='error')\n",
@@ -315,7 +361,7 @@
},
{
"cell_type": "markdown",
- "id": "fdeee7ba",
+ "id": "e68ca037",
"metadata": {},
"source": [
"Now let us vary $\\alpha$ (holding $\\beta$ constant)"
@@ -324,7 +370,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "5511e518",
+ "id": "f28f446b",
"metadata": {},
"outputs": [],
"source": [
@@ -335,17 +381,24 @@
},
{
"cell_type": "markdown",
- "id": "4192ba4a",
+ "id": "693e3ab9",
"metadata": {},
"source": [
- "Ploting the error"
+ "Plotting the error"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "a2410b18",
- "metadata": {},
+ "id": "ffd945fb",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Plotting the error (2)",
+ "name": "plt-errors-2"
+ }
+ }
+ },
"outputs": [],
"source": [
"ax = pd.Series(errors).plot(xlabel='α', ylabel='error')\n",
@@ -354,11 +407,11 @@
},
{
"cell_type": "markdown",
- "id": "e3a1a2a6",
+ "id": "dc3045a1",
"metadata": {},
"source": [
"(slr:optimal-values)=\n",
- "## Calculating Optimal Values\n",
+ "## Calculating optimal values\n",
"\n",
"Now let us use calculus to solve the optimization problem and compute the optimal values for $\\alpha$ and $\\beta$ to find the ordinary least squares solution.\n",
"\n",
@@ -460,20 +513,20 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "1f36ba79",
+ "id": "7838f7f2",
"metadata": {},
"outputs": [],
"source": [
"df = df[['X','Y']].copy() # Original Data\n",
"\n",
- "# Calcuate the sample means\n",
+ "# Calculate the sample means\n",
"x_bar = df['X'].mean()\n",
"y_bar = df['Y'].mean()"
]
},
{
"cell_type": "markdown",
- "id": "0d423b6b",
+ "id": "b34ad3e3",
"metadata": {},
"source": [
"Now computing across the 10 observations and then summing the numerator and denominator"
@@ -482,7 +535,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "a74fc923",
+ "id": "5409ff1a",
"metadata": {},
"outputs": [],
"source": [
@@ -495,7 +548,7 @@
},
{
"cell_type": "markdown",
- "id": "91d13a4a",
+ "id": "b6327213",
"metadata": {},
"source": [
"Calculating $\\alpha$"
@@ -504,7 +557,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "9ee6bed4",
+ "id": "23eaf8bc",
"metadata": {},
"outputs": [],
"source": [
@@ -514,7 +567,7 @@
},
{
"cell_type": "markdown",
- "id": "b59f03c5",
+ "id": "73010edb",
"metadata": {},
"source": [
"Now we can plot the OLS solution"
@@ -523,31 +576,31 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "d7230f9e",
- "metadata": {},
+ "id": "f60828b2",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "OLS line of best fit",
+ "name": "plt-ols"
+ }
+ }
+ },
"outputs": [],
"source": [
"df['Y_hat'] = α + β * df['X']\n",
"df['error'] = df['Y_hat'] - df['Y']\n",
"\n",
"fig, ax = plt.subplots()\n",
- "df.plot(x='X',y='Y', kind='scatter', ax=ax)\n",
- "df.plot(x='X',y='Y_hat', kind='line', ax=ax, color='g')\n",
+ "ax = df.plot(x='X',y='Y', kind='scatter', ax=ax)\n",
+ "ax = df.plot(x='X',y='Y_hat', kind='line', ax=ax, color='g')\n",
"plt.vlines(df['X'], df['Y_hat'], df['Y'], color='r');"
]
},
{
"cell_type": "markdown",
- "id": "74ba0e40",
+ "id": "80beb480",
"metadata": {},
"source": [
- ":::{admonition} Why use OLS?\n",
- "TODO\n",
- "\n",
- "1. Discuss mathematical properties for why we have chosen OLS\n",
- ":::\n",
- "\n",
- "\n",
":::{exercise}\n",
":label: slr-ex1\n",
"\n",
@@ -557,7 +610,7 @@
"\n",
"1. What do you think their relationship would be?\n",
"2. Gather some data [from our world in data](https://ourworldindata.org)\n",
- "3. Use `pandas` to import the `csv` formated data and plot a few different countries of interest\n",
+ "3. Use `pandas` to import the `csv` formatted data and plot a few different countries of interest\n",
"4. Use {eq}`eq:optimal-alpha` and {eq}`eq:optimal-beta` to compute optimal values for $\\alpha$ and $\\beta$\n",
"5. Plot the line of best fit found using OLS\n",
"6. Interpret the coefficients and write a summary sentence of the relationship between GDP per capita and Life Expectancy\n",
@@ -573,7 +626,7 @@
"\n",
":::\n",
"\n",
- "You can download {download}`a copy of the data here <_static/lecture_specific/simple_linear_regression/life-expectancy-vs-gdp-per-capita.csv>` if you get stuck\n",
+ "You can download {download}`a copy of the data here ` if you get stuck\n",
"\n",
"**Q3:** Use `pandas` to import the `csv` formatted data and plot a few different countries of interest"
]
@@ -581,18 +634,18 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "4f71b466",
+ "id": "eedab539",
"metadata": {},
"outputs": [],
"source": [
- "fl = \"_static/lecture_specific/simple_linear_regression/life-expectancy-vs-gdp-per-capita.csv\" # TODO: Replace with GitHub link\n",
- "df = pd.read_csv(fl, nrows=10)"
+ "data_url = \"https://github.com/QuantEcon/lecture-python-intro/raw/main/lectures/_static/lecture_specific/simple_linear_regression/life-expectancy-vs-gdp-per-capita.csv\"\n",
+ "df = pd.read_csv(data_url, nrows=10)"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "3d25f4ba",
+ "id": "d27a9e52",
"metadata": {},
"outputs": [],
"source": [
@@ -601,7 +654,7 @@
},
{
"cell_type": "markdown",
- "id": "7bc25088",
+ "id": "74ae9410",
"metadata": {},
"source": [
"You can see that the data downloaded from Our World in Data has provided a global set of countries with the GDP per capita and Life Expectancy Data.\n",
@@ -616,18 +669,18 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "c45d5967",
+ "id": "21ea2277",
"metadata": {},
"outputs": [],
"source": [
"cols = ['Code', 'Year', 'Life expectancy at birth (historical)', 'GDP per capita']\n",
- "df = pd.read_csv(fl, usecols=cols)\n",
+ "df = pd.read_csv(data_url, usecols=cols)\n",
"df"
]
},
{
"cell_type": "markdown",
- "id": "5307f3f9",
+ "id": "50d4a3b3",
"metadata": {},
"source": [
"Sometimes it can be useful to rename your columns to make it easier to work with in the DataFrame"
@@ -636,17 +689,17 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "7727695f",
+ "id": "86abda5b",
"metadata": {},
"outputs": [],
"source": [
- "df.columns = [\"cntry\", \"year\", \"life_expectency\", \"gdppc\"]\n",
+ "df.columns = [\"cntry\", \"year\", \"life_expectancy\", \"gdppc\"]\n",
"df"
]
},
{
"cell_type": "markdown",
- "id": "a5e801b1",
+ "id": "12a7770a",
"metadata": {},
"source": [
"We can see there are `NaN` values which represents missing data so let us go ahead and drop those"
@@ -655,7 +708,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "d340c231",
+ "id": "a1ffb39c",
"metadata": {},
"outputs": [],
"source": [
@@ -665,7 +718,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "c7ca0e82",
+ "id": "28f68c1c",
"metadata": {},
"outputs": [],
"source": [
@@ -674,7 +727,7 @@
},
{
"cell_type": "markdown",
- "id": "499856c9",
+ "id": "71842265",
"metadata": {},
"source": [
"We have now dropped the number of rows in our DataFrame from 62156 to 12445 removing a lot of empty data relationships.\n",
@@ -685,23 +738,23 @@
"\n",
"For example, you may want to explore this data to see if there is consistent reporting for all countries across years\n",
"\n",
- "Let's first look at the Life Expectency Data"
+ "Let's first look at the Life Expectancy Data"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "666653c3",
+ "id": "2fb32504",
"metadata": {},
"outputs": [],
"source": [
- "le_years = df[['cntry', 'year', 'life_expectency']].set_index(['cntry', 'year']).unstack()['life_expectency']\n",
+ "le_years = df[['cntry', 'year', 'life_expectancy']].set_index(['cntry', 'year']).unstack()['life_expectancy']\n",
"le_years"
]
},
{
"cell_type": "markdown",
- "id": "08620061",
+ "id": "d2836675",
"metadata": {},
"source": [
"As you can see there are a lot of countries where data is not available for the Year 1543!\n",
@@ -712,7 +765,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "5ef52fc2",
+ "id": "b85bf985",
"metadata": {},
"outputs": [],
"source": [
@@ -721,7 +774,7 @@
},
{
"cell_type": "markdown",
- "id": "60007a50",
+ "id": "44a4b3d9",
"metadata": {},
"source": [
"You can see that Great Britain (GBR) is the only one available\n",
@@ -732,7 +785,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "9091df2a",
+ "id": "6328e690",
"metadata": {},
"outputs": [],
"source": [
@@ -741,7 +794,7 @@
},
{
"cell_type": "markdown",
- "id": "71bec900",
+ "id": "5d5d858e",
"metadata": {},
"source": [
"In fact we can use pandas to quickly check how many countries are captured in each year"
@@ -750,7 +803,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "f8386093",
+ "id": "f951ca10",
"metadata": {},
"outputs": [],
"source": [
@@ -759,7 +812,7 @@
},
{
"cell_type": "markdown",
- "id": "1916e084",
+ "id": "0abee961",
"metadata": {},
"source": [
"So it is clear that if you are doing cross-sectional comparisons then more recent data will include a wider set of countries\n",
@@ -770,7 +823,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "5e643825",
+ "id": "1bb749c8",
"metadata": {},
"outputs": [],
"source": [
@@ -780,28 +833,24 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "11c21bab",
+ "id": "d785aa89",
"metadata": {},
"outputs": [],
"source": [
- "df.plot(x='gdppc', y='life_expectency', kind='scatter', xlabel=\"GDP per capita\", ylabel=\"Life Expectency (Years)\",);"
+ "df.plot(x='gdppc', y='life_expectancy', kind='scatter', xlabel=\"GDP per capita\", ylabel=\"Life expectancy (years)\",);"
]
},
{
"cell_type": "markdown",
- "id": "3e993aea",
+ "id": "fcb75b10",
"metadata": {},
"source": [
"This data shows a couple of interesting relationships.\n",
"\n",
"1. there are a number of countries with similar GDP per capita levels but a wide range in Life Expectancy\n",
- "2. there appears to be a positive relationship between GDP per capita and life expectancy. Countries with higher GDP per capita tend to have higher life expectency outcomes\n",
+ "2. there appears to be a positive relationship between GDP per capita and life expectancy. Countries with higher GDP per capita tend to have higher life expectancy outcomes\n",
"\n",
- "Even though OLS is solving linear equations -- one option we have is to transform the variables, such as through a log transform, and then use OLS to estimate the transformed variables\n",
- "\n",
- ":::{tip}\n",
- "ln -> ln == elasticities\n",
- ":::\n",
+ "Even though OLS is solving linear equations -- one option we have is to transform the variables, such as through a log transform, and then use OLS to estimate the transformed variables.\n",
"\n",
"By specifying `logx` you can plot the GDP per Capita data on a log scale"
]
@@ -809,16 +858,16 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "be844bb2",
+ "id": "980376ba",
"metadata": {},
"outputs": [],
"source": [
- "df.plot(x='gdppc', y='life_expectency', kind='scatter', xlabel=\"GDP per capita\", ylabel=\"Life Expectancy (Years)\", logx=True);"
+ "df.plot(x='gdppc', y='life_expectancy', kind='scatter', xlabel=\"GDP per capita\", ylabel=\"Life expectancy (years)\", logx=True);"
]
},
{
"cell_type": "markdown",
- "id": "d58ce1b6",
+ "id": "1a001f1c",
"metadata": {},
"source": [
"As you can see from this transformation -- a linear model fits the shape of the data more closely."
@@ -827,7 +876,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "4d3d1a44",
+ "id": "26ea82ad",
"metadata": {},
"outputs": [],
"source": [
@@ -837,7 +886,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "b03737c8",
+ "id": "531e05b6",
"metadata": {},
"outputs": [],
"source": [
@@ -846,7 +895,7 @@
},
{
"cell_type": "markdown",
- "id": "88cdf442",
+ "id": "0ed1153a",
"metadata": {},
"source": [
"**Q4:** Use {eq}`eq:optimal-alpha` and {eq}`eq:optimal-beta` to compute optimal values for $\\alpha$ and $\\beta$"
@@ -855,21 +904,21 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "c201f3fd",
+ "id": "c8e5a743",
"metadata": {},
"outputs": [],
"source": [
- "data = df[['log_gdppc', 'life_expectency']].copy() # Get Data from DataFrame\n",
+ "data = df[['log_gdppc', 'life_expectancy']].copy() # Get Data from DataFrame\n",
"\n",
"# Calculate the sample means\n",
"x_bar = data['log_gdppc'].mean()\n",
- "y_bar = data['life_expectency'].mean()"
+ "y_bar = data['life_expectancy'].mean()"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "c11388ea",
+ "id": "61177203",
"metadata": {},
"outputs": [],
"source": [
@@ -879,12 +928,12 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "2a7672fd",
+ "id": "b5181988",
"metadata": {},
"outputs": [],
"source": [
"# Compute the Sums\n",
- "data['num'] = data['log_gdppc'] * data['life_expectency'] - y_bar * data['log_gdppc']\n",
+ "data['num'] = data['log_gdppc'] * data['life_expectancy'] - y_bar * data['log_gdppc']\n",
"data['den'] = pow(data['log_gdppc'],2) - x_bar * data['log_gdppc']\n",
"β = data['num'].sum() / data['den'].sum()\n",
"print(β)"
@@ -893,7 +942,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "cc3a7f79",
+ "id": "2436826e",
"metadata": {},
"outputs": [],
"source": [
@@ -903,7 +952,7 @@
},
{
"cell_type": "markdown",
- "id": "971cdaf3",
+ "id": "f692e427",
"metadata": {},
"source": [
"**Q5:** Plot the line of best fit found using OLS"
@@ -912,22 +961,22 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "da63bfab",
+ "id": "6515f862",
"metadata": {},
"outputs": [],
"source": [
- "data['life_expectency_hat'] = α + β * df['log_gdppc']\n",
- "data['error'] = data['life_expectency_hat'] - data['life_expectency']\n",
+ "data['life_expectancy_hat'] = α + β * df['log_gdppc']\n",
+ "data['error'] = data['life_expectancy_hat'] - data['life_expectancy']\n",
"\n",
"fig, ax = plt.subplots()\n",
- "data.plot(x='log_gdppc',y='life_expectency', kind='scatter', ax=ax)\n",
- "data.plot(x='log_gdppc',y='life_expectency_hat', kind='line', ax=ax, color='g')\n",
- "plt.vlines(data['log_gdppc'], data['life_expectency_hat'], data['life_expectency'], color='r')"
+ "data.plot(x='log_gdppc',y='life_expectancy', kind='scatter', ax=ax)\n",
+ "data.plot(x='log_gdppc',y='life_expectancy_hat', kind='line', ax=ax, color='g')\n",
+ "plt.vlines(data['log_gdppc'], data['life_expectancy_hat'], data['life_expectancy'], color='r')"
]
},
{
"cell_type": "markdown",
- "id": "60a2aef6",
+ "id": "cc408af1",
"metadata": {},
"source": [
":::{solution-end}\n",
@@ -936,9 +985,9 @@
":::{exercise}\n",
":label: slr-ex2\n",
"\n",
- "Minimising the sum of squares is not the **only** way to generate the line of best fit. \n",
+ "Minimizing the sum of squares is not the **only** way to generate the line of best fit. \n",
"\n",
- "For example, we could also consider minimising the sum of the **absolute values**, that would give less weight to outliers. \n",
+ "For example, we could also consider minimizing the sum of the **absolute values**, that would give less weight to outliers. \n",
"\n",
"Solve for $\\alpha$ and $\\beta$ using the least absolute values\n",
":::"
@@ -946,12 +995,92 @@
}
],
"metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.14.4"
+ }
+ },
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
- }
+ },
+ "source_map": [
+ 12,
+ 16,
+ 20,
+ 49,
+ 55,
+ 59,
+ 73,
+ 85,
+ 91,
+ 102,
+ 108,
+ 113,
+ 126,
+ 131,
+ 142,
+ 155,
+ 159,
+ 163,
+ 175,
+ 197,
+ 200,
+ 204,
+ 208,
+ 212,
+ 221,
+ 225,
+ 229,
+ 233,
+ 242,
+ 343,
+ 349,
+ 353,
+ 359,
+ 363,
+ 366,
+ 370,
+ 384,
+ 415,
+ 420,
+ 422,
+ 432,
+ 436,
+ 440,
+ 443,
+ 447,
+ 451,
+ 453,
+ 465,
+ 468,
+ 474,
+ 476,
+ 482,
+ 484,
+ 488,
+ 490,
+ 496,
+ 500,
+ 502,
+ 513,
+ 515,
+ 519,
+ 523,
+ 525,
+ 529,
+ 537,
+ 541,
+ 549,
+ 552,
+ 556,
+ 564
+ ]
},
"nbformat": 4,
"nbformat_minor": 5
-}
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/simple_linear_regression.md b/book/_build/html/_sources/simple_linear_regression.md
new file mode 100644
index 0000000..137d453
--- /dev/null
+++ b/book/_build/html/_sources/simple_linear_regression.md
@@ -0,0 +1,577 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.14.4
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+# Simple Linear Regression Model
+
+```{code-cell} ipython3
+import numpy as np
+import pandas as pd
+import matplotlib.pyplot as plt
+```
+
+The simple regression model estimates the relationship between two variables $x_i$ and $y_i$
+
+$$
+y_i = \alpha + \beta x_i + \epsilon_i, i = 1,2,...,N
+$$
+
+where $\epsilon_i$ represents the error between the line of best fit and the sample values for $y_i$ given $x_i$.
+
+Our goal is to choose values for $\alpha$ and $\beta$ to build a line of "best" fit for some data that is available for variables $x_i$ and $y_i$.
+
+Let us consider a simple dataset of 10 observations for variables $x_i$ and $y_i$:
+
+| | $y_i$ | $x_i$ |
+|-|---|---|
+|1| 2000 | 32 |
+|2| 1000 | 21 |
+|3| 1500 | 24 |
+|4| 2500 | 35 |
+|5| 500 | 10 |
+|6| 900 | 11 |
+|7| 1100 | 22 |
+|8| 1500 | 21 |
+|9| 1800 | 27 |
+|10 | 250 | 2 |
+
+Let us think about $y_i$ as sales for an ice-cream cart, while $x_i$ is a variable that records the day's temperature in Celsius.
+
+```{code-cell} ipython3
+x = [32, 21, 24, 35, 10, 11, 22, 21, 27, 2]
+y = [2000,1000,1500,2500,500,900,1100,1500,1800, 250]
+df = pd.DataFrame([x,y]).T
+df.columns = ['X', 'Y']
+df
+```
+
+We can use a scatter plot of the data to see the relationship between $y_i$ (ice-cream sales in dollars (\$\'s)) and $x_i$ (degrees Celsius).
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Scatter plot"
+ name: sales-v-temp1
+---
+ax = df.plot(
+ x='X',
+ y='Y',
+ kind='scatter',
+ ylabel='Ice-cream sales ($\'s)',
+ xlabel='Degrees celcius'
+)
+```
+
+as you can see the data suggests that more ice-cream is typically sold on hotter days.
+
+To build a linear model of the data we need to choose values for $\alpha$ and $\beta$ that represents a line of "best" fit such that
+
+$$
+\hat{y_i} = \hat{\alpha} + \hat{\beta} x_i
+$$
+
+Let's start with $\alpha = 5$ and $\beta = 10$
+
+```{code-cell} ipython3
+α = 5
+β = 10
+df['Y_hat'] = α + β * df['X']
+```
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Scatter plot with a line of fit"
+ name: sales-v-temp2
+---
+fig, ax = plt.subplots()
+ax = df.plot(x='X',y='Y', kind='scatter', ax=ax)
+ax = df.plot(x='X',y='Y_hat', kind='line', ax=ax)
+plt.show()
+```
+
+We can see that this model does a poor job of estimating the relationship.
+
+We can continue to guess and iterate towards a line of "best" fit by adjusting the parameters
+
+```{code-cell} ipython3
+β = 100
+df['Y_hat'] = α + β * df['X']
+```
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Scatter plot with a line of fit #2"
+ name: sales-v-temp3
+---
+fig, ax = plt.subplots()
+ax = df.plot(x='X',y='Y', kind='scatter', ax=ax)
+ax = df.plot(x='X',y='Y_hat', kind='line', ax=ax)
+plt.show()
+```
+
+```{code-cell} ipython3
+β = 65
+df['Y_hat'] = α + β * df['X']
+```
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Scatter plot with a line of fit #3"
+ name: sales-v-temp4
+---
+fig, ax = plt.subplots()
+ax = df.plot(x='X',y='Y', kind='scatter', ax=ax)
+ax = df.plot(x='X',y='Y_hat', kind='line', ax=ax, color='g')
+plt.show()
+```
+
+However we need to think about formalizing this guessing process by thinking of this problem as an optimization problem.
+
+Let's consider the error $\epsilon_i$ and define the difference between the observed values $y_i$ and the estimated values $\hat{y}_i$ which we will call the residuals
+
+$$
+\begin{aligned}
+\hat{e}_i &= y_i - \hat{y}_i \\
+ &= y_i - \hat{\alpha} - \hat{\beta} x_i
+\end{aligned}
+$$
+
+```{code-cell} ipython3
+df['error'] = df['Y_hat'] - df['Y']
+```
+
+```{code-cell} ipython3
+df
+```
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Plot of the residuals"
+ name: plt-residuals
+---
+fig, ax = plt.subplots()
+ax = df.plot(x='X',y='Y', kind='scatter', ax=ax)
+ax = df.plot(x='X',y='Y_hat', kind='line', ax=ax, color='g')
+plt.vlines(df['X'], df['Y_hat'], df['Y'], color='r')
+plt.show()
+```
+
+The Ordinary Least Squares (OLS) method chooses $\alpha$ and $\beta$ in such a way that **minimizes** the sum of the squared residuals (SSR).
+
+$$
+\min_{\alpha,\beta} \sum_{i=1}^{N}{\hat{e}_i^2} = \min_{\alpha,\beta} \sum_{i=1}^{N}{(y_i - \alpha - \beta x_i)^2}
+$$
+
+Let's call this a cost function
+
+$$
+C = \sum_{i=1}^{N}{(y_i - \alpha - \beta x_i)^2}
+$$
+
+that we would like to minimize with parameters $\alpha$ and $\beta$.
+
+## How does error change with respect to $\alpha$ and $\beta$
+
+Let us first look at how the total error changes with respect to $\beta$ (holding the intercept $\alpha$ constant)
+
+We know from [the next section](slr:optimal-values) the optimal values for $\alpha$ and $\beta$ are:
+
+```{code-cell} ipython3
+β_optimal = 64.38
+α_optimal = -14.72
+```
+
+We can then calculate the error for a range of $\beta$ values
+
+```{code-cell} ipython3
+errors = {}
+for β in np.arange(20,100,0.5):
+ errors[β] = abs((α_optimal + β * df['X']) - df['Y']).sum()
+```
+
+Plotting the error
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Plotting the error"
+ name: plt-errors
+---
+ax = pd.Series(errors).plot(xlabel='β', ylabel='error')
+plt.axvline(β_optimal, color='r');
+```
+
+Now let us vary $\alpha$ (holding $\beta$ constant)
+
+```{code-cell} ipython3
+errors = {}
+for α in np.arange(-500,500,5):
+ errors[α] = abs((α + β_optimal * df['X']) - df['Y']).sum()
+```
+
+Plotting the error
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Plotting the error (2)"
+ name: plt-errors-2
+---
+ax = pd.Series(errors).plot(xlabel='α', ylabel='error')
+plt.axvline(α_optimal, color='r');
+```
+
+(slr:optimal-values)=
+## Calculating optimal values
+
+Now let us use calculus to solve the optimization problem and compute the optimal values for $\alpha$ and $\beta$ to find the ordinary least squares solution.
+
+First taking the partial derivative with respect to $\alpha$
+
+$$
+\frac{\partial C}{\partial \alpha}[\sum_{i=1}^{N}{(y_i - \alpha - \beta x_i)^2}]
+$$
+
+and setting it equal to $0$
+
+$$
+0 = \sum_{i=1}^{N}{-2(y_i - \alpha - \beta x_i)}
+$$
+
+we can remove the constant $-2$ from the summation by dividing both sides by $-2$
+
+$$
+0 = \sum_{i=1}^{N}{(y_i - \alpha - \beta x_i)}
+$$
+
+Now we can split this equation up into the components
+
+$$
+0 = \sum_{i=1}^{N}{y_i} - \sum_{i=1}^{N}{\alpha} - \beta \sum_{i=1}^{N}{x_i}
+$$
+
+The middle term is a straight forward sum from $i=1,...N$ by a constant $\alpha$
+
+$$
+0 = \sum_{i=1}^{N}{y_i} - N*\alpha - \beta \sum_{i=1}^{N}{x_i}
+$$
+
+and rearranging terms
+
+$$
+\alpha = \frac{\sum_{i=1}^{N}{y_i} - \beta \sum_{i=1}^{N}{x_i}}{N}
+$$
+
+We observe that both fractions resolve to the means $\bar{y_i}$ and $\bar{x_i}$
+
+$$
+\alpha = \bar{y_i} - \beta\bar{x_i}
+$$ (eq:optimal-alpha)
+
+Now let's take the partial derivative of the cost function $C$ with respect to $\beta$
+
+$$
+\frac{\partial C}{\partial \beta}[\sum_{i=1}^{N}{(y_i - \alpha - \beta x_i)^2}]
+$$
+
+and setting it equal to $0$
+
+$$
+0 = \sum_{i=1}^{N}{-2 x_i (y_i - \alpha - \beta x_i)}
+$$
+
+we can again take the constant outside of the summation and divide both sides by $-2$
+
+$$
+0 = \sum_{i=1}^{N}{x_i (y_i - \alpha - \beta x_i)}
+$$
+
+which becomes
+
+$$
+0 = \sum_{i=1}^{N}{(x_i y_i - \alpha x_i - \beta x_i^2)}
+$$
+
+now substituting for $\alpha$
+
+$$
+0 = \sum_{i=1}^{N}{(x_i y_i - (\bar{y_i} - \beta \bar{x_i}) x_i - \beta x_i^2)}
+$$
+
+and rearranging terms
+
+$$
+0 = \sum_{i=1}^{N}{(x_i y_i - \bar{y_i} x_i - \beta \bar{x_i} x_i - \beta x_i^2)}
+$$
+
+This can be split into two summations
+
+$$
+0 = \sum_{i=1}^{N}(x_i y_i - \bar{y_i} x_i) + \beta \sum_{i=1}^{N}(\bar{x_i} x_i - x_i^2)
+$$
+
+and solving for $\beta$ yields
+
+$$
+\beta = \frac{\sum_{i=1}^{N}(x_i y_i - \bar{y_i} x_i)}{\sum_{i=1}^{N}(x_i^2 - \bar{x_i} x_i)}
+$$ (eq:optimal-beta)
+
+We can now use {eq}`eq:optimal-alpha` and {eq}`eq:optimal-beta` to calculate the optimal values for $\alpha$ and $\beta$
+
+Calculating $\beta$
+
+```{code-cell} ipython3
+df = df[['X','Y']].copy() # Original Data
+
+# Calculate the sample means
+x_bar = df['X'].mean()
+y_bar = df['Y'].mean()
+```
+
+Now computing across the 10 observations and then summing the numerator and denominator
+
+```{code-cell} ipython3
+# Compute the Sums
+df['num'] = df['X'] * df['Y'] - y_bar * df['X']
+df['den'] = pow(df['X'],2) - x_bar * df['X']
+β = df['num'].sum() / df['den'].sum()
+print(β)
+```
+
+Calculating $\alpha$
+
+```{code-cell} ipython3
+α = y_bar - β * x_bar
+print(α)
+```
+
+Now we can plot the OLS solution
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "OLS line of best fit"
+ name: plt-ols
+---
+df['Y_hat'] = α + β * df['X']
+df['error'] = df['Y_hat'] - df['Y']
+
+fig, ax = plt.subplots()
+ax = df.plot(x='X',y='Y', kind='scatter', ax=ax)
+ax = df.plot(x='X',y='Y_hat', kind='line', ax=ax, color='g')
+plt.vlines(df['X'], df['Y_hat'], df['Y'], color='r');
+```
+
+:::{exercise}
+:label: slr-ex1
+
+Now that you know the equations that solve the simple linear regression model using OLS you can now run your own regressions to build a model between $y$ and $x$.
+
+Let's consider two economic variables GDP per capita and Life Expectancy.
+
+1. What do you think their relationship would be?
+2. Gather some data [from our world in data](https://ourworldindata.org)
+3. Use `pandas` to import the `csv` formatted data and plot a few different countries of interest
+4. Use {eq}`eq:optimal-alpha` and {eq}`eq:optimal-beta` to compute optimal values for $\alpha$ and $\beta$
+5. Plot the line of best fit found using OLS
+6. Interpret the coefficients and write a summary sentence of the relationship between GDP per capita and Life Expectancy
+
+:::
+
+:::{solution-start} slr-ex1
+:::
+
+**Q2:** Gather some data [from our world in data](https://ourworldindata.org)
+
+:::{raw} html
+
+:::
+
+You can download {download}`a copy of the data here ` if you get stuck
+
+**Q3:** Use `pandas` to import the `csv` formatted data and plot a few different countries of interest
+
+```{code-cell} ipython3
+data_url = "https://github.com/QuantEcon/lecture-python-intro/raw/main/lectures/_static/lecture_specific/simple_linear_regression/life-expectancy-vs-gdp-per-capita.csv"
+df = pd.read_csv(data_url, nrows=10)
+```
+
+```{code-cell} ipython3
+df
+```
+
+You can see that the data downloaded from Our World in Data has provided a global set of countries with the GDP per capita and Life Expectancy Data.
+
+It is often a good idea to at first import a few lines of data from a csv to understand its structure so that you can then choose the columns that you want to read into your DataFrame.
+
+You can observe that there are a bunch of columns we won't need to import such as `Continent`
+
+So let's built a list of the columns we want to import
+
+```{code-cell} ipython3
+cols = ['Code', 'Year', 'Life expectancy at birth (historical)', 'GDP per capita']
+df = pd.read_csv(data_url, usecols=cols)
+df
+```
+
+Sometimes it can be useful to rename your columns to make it easier to work with in the DataFrame
+
+```{code-cell} ipython3
+df.columns = ["cntry", "year", "life_expectancy", "gdppc"]
+df
+```
+
+We can see there are `NaN` values which represents missing data so let us go ahead and drop those
+
+```{code-cell} ipython3
+df.dropna(inplace=True)
+```
+
+```{code-cell} ipython3
+df
+```
+
+We have now dropped the number of rows in our DataFrame from 62156 to 12445 removing a lot of empty data relationships.
+
+Now we have a dataset containing life expectancy and GDP per capita for a range of years.
+
+It is always a good idea to spend a bit of time understanding what data you actually have.
+
+For example, you may want to explore this data to see if there is consistent reporting for all countries across years
+
+Let's first look at the Life Expectancy Data
+
+```{code-cell} ipython3
+le_years = df[['cntry', 'year', 'life_expectancy']].set_index(['cntry', 'year']).unstack()['life_expectancy']
+le_years
+```
+
+As you can see there are a lot of countries where data is not available for the Year 1543!
+
+Which country does report this data?
+
+```{code-cell} ipython3
+le_years[~le_years[1543].isna()]
+```
+
+You can see that Great Britain (GBR) is the only one available
+
+You can also take a closer look at the time series to find that it is also non-continuous, even for GBR.
+
+```{code-cell} ipython3
+le_years.loc['GBR'].plot()
+```
+
+In fact we can use pandas to quickly check how many countries are captured in each year
+
+```{code-cell} ipython3
+le_years.stack().unstack(level=0).count(axis=1).plot(xlabel="Year", ylabel="Number of countries");
+```
+
+So it is clear that if you are doing cross-sectional comparisons then more recent data will include a wider set of countries
+
+Now let us consider the most recent year in the dataset 2018
+
+```{code-cell} ipython3
+df = df[df.year == 2018].reset_index(drop=True).copy()
+```
+
+```{code-cell} ipython3
+df.plot(x='gdppc', y='life_expectancy', kind='scatter', xlabel="GDP per capita", ylabel="Life expectancy (years)",);
+```
+
+This data shows a couple of interesting relationships.
+
+1. there are a number of countries with similar GDP per capita levels but a wide range in Life Expectancy
+2. there appears to be a positive relationship between GDP per capita and life expectancy. Countries with higher GDP per capita tend to have higher life expectancy outcomes
+
+Even though OLS is solving linear equations -- one option we have is to transform the variables, such as through a log transform, and then use OLS to estimate the transformed variables.
+
+By specifying `logx` you can plot the GDP per Capita data on a log scale
+
+```{code-cell} ipython3
+df.plot(x='gdppc', y='life_expectancy', kind='scatter', xlabel="GDP per capita", ylabel="Life expectancy (years)", logx=True);
+```
+
+As you can see from this transformation -- a linear model fits the shape of the data more closely.
+
+```{code-cell} ipython3
+df['log_gdppc'] = df['gdppc'].apply(np.log10)
+```
+
+```{code-cell} ipython3
+df
+```
+
+**Q4:** Use {eq}`eq:optimal-alpha` and {eq}`eq:optimal-beta` to compute optimal values for $\alpha$ and $\beta$
+
+```{code-cell} ipython3
+data = df[['log_gdppc', 'life_expectancy']].copy() # Get Data from DataFrame
+
+# Calculate the sample means
+x_bar = data['log_gdppc'].mean()
+y_bar = data['life_expectancy'].mean()
+```
+
+```{code-cell} ipython3
+data
+```
+
+```{code-cell} ipython3
+# Compute the Sums
+data['num'] = data['log_gdppc'] * data['life_expectancy'] - y_bar * data['log_gdppc']
+data['den'] = pow(data['log_gdppc'],2) - x_bar * data['log_gdppc']
+β = data['num'].sum() / data['den'].sum()
+print(β)
+```
+
+```{code-cell} ipython3
+α = y_bar - β * x_bar
+print(α)
+```
+
+**Q5:** Plot the line of best fit found using OLS
+
+```{code-cell} ipython3
+data['life_expectancy_hat'] = α + β * df['log_gdppc']
+data['error'] = data['life_expectancy_hat'] - data['life_expectancy']
+
+fig, ax = plt.subplots()
+data.plot(x='log_gdppc',y='life_expectancy', kind='scatter', ax=ax)
+data.plot(x='log_gdppc',y='life_expectancy_hat', kind='line', ax=ax, color='g')
+plt.vlines(data['log_gdppc'], data['life_expectancy_hat'], data['life_expectancy'], color='r')
+```
+
+:::{solution-end}
+:::
+
+:::{exercise}
+:label: slr-ex2
+
+Minimizing the sum of squares is not the **only** way to generate the line of best fit.
+
+For example, we could also consider minimizing the sum of the **absolute values**, that would give less weight to outliers.
+
+Solve for $\alpha$ and $\beta$ using the least absolute values
+:::
diff --git a/content/lectures/solow.ipynb b/book/_build/html/_sources/solow.ipynb
similarity index 88%
rename from content/lectures/solow.ipynb
rename to book/_build/html/_sources/solow.ipynb
index 8c771d0..82bc5df 100644
--- a/content/lectures/solow.ipynb
+++ b/book/_build/html/_sources/solow.ipynb
@@ -2,27 +2,27 @@
"cells": [
{
"cell_type": "markdown",
- "id": "5f8ce0da",
+ "id": "86f9c185",
"metadata": {},
"source": [
"(solow)=\n",
"# The Solow-Swan Growth Model\n",
"\n",
"In this lecture we review a famous model due\n",
- "to [Robert Solow (1925--2014)](https://en.wikipedia.org/wiki/Robert_Solow) and [Trevor Swan (1918--1989)](https://en.wikipedia.org/wiki/Trevor_Swan).\n",
+ "to [Robert Solow (1925--2023)](https://en.wikipedia.org/wiki/Robert_Solow) and [Trevor Swan (1918--1989)](https://en.wikipedia.org/wiki/Trevor_Swan).\n",
"\n",
"The model is used to study growth over the long run.\n",
"\n",
"Although the model is simple, it contains some interesting lessons.\n",
"\n",
"\n",
- "We will use the following imports"
+ "We will use the following imports."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "de963928",
+ "id": "7f442c67",
"metadata": {},
"outputs": [],
"source": [
@@ -32,10 +32,10 @@
},
{
"cell_type": "markdown",
- "id": "4bccaeed",
+ "id": "fdee4981",
"metadata": {},
"source": [
- "## The Model\n",
+ "## The model\n",
"\n",
"In a Solow--Swan economy, agents save a fixed fraction of their current\n",
"incomes.\n",
@@ -63,11 +63,13 @@
"Production functions with this property include\n",
"\n",
"* the **Cobb-Douglas** function $F(K, L) = A K^{\\alpha}\n",
- " L^{1-\\alpha}$ with $0 \\leq \\alpha \\leq 1$ and\n",
+ " L^{1-\\alpha}$ with $0 \\leq \\alpha \\leq 1$. \n",
"* the **CES** function $F(K, L) = \\left\\{ a K^\\rho + b L^\\rho \\right\\}^{1/\\rho}$\n",
- " with $a, b, \\rho > 0$.\n",
+ " with $a, b, \\rho > 0$. \n",
+ " \n",
+ "Here, $\\alpha$ is the output elasticity of capital and $\\rho$ is a parameter that determines the elasticity of substitution between capital and labor.\n",
"\n",
- "We assume a closed economy, so domestic investment equals aggregate domestic\n",
+ "We assume a closed economy, so aggregate domestic investment equals aggregate domestic\n",
"saving.\n",
"\n",
"The saving rate is a constant $s$ satisfying $0 \\leq s \\leq 1$, so that aggregate\n",
@@ -89,6 +91,7 @@
"\n",
"$$\n",
" k_{t+1}\n",
+ " = s \\frac{F(K_t, L)}{L} + (1 - \\delta) \\frac{K_t}{L}\n",
" = s \\frac{F(K_t, L)}{L} + (1 - \\delta) k_t\n",
" = s F(k_t, 1) + (1 - \\delta) k_t\n",
"$$\n",
@@ -106,10 +109,9 @@
"given an exogenous initial capital stock $k_0$.\n",
"\n",
"\n",
- "## A Graphical Perspective\n",
+ "## A graphical perspective\n",
"\n",
- "To understand the dynamics of the sequence $(k_t)_{t \\geq 0}$ we use a 45\n",
- "degree diagram.\n",
+ "To understand the dynamics of the sequence $(k_t)_{t \\geq 0}$ we use a 45-degree diagram.\n",
"\n",
"To do so, we first\n",
"need to specify the functional form for $f$ and assign values to the parameters.\n",
@@ -117,8 +119,7 @@
"We choose the Cobb--Douglas specification $f(k) = A k^\\alpha$ and set $A=2.0$,\n",
"$\\alpha=0.3$, $s=0.3$ and $\\delta=0.4$.\n",
"\n",
- "The function $g$ from {eq}`solow` is then plotted, along with the 45\n",
- "degree line.\n",
+ "The function $g$ from {eq}`solow` is then plotted, along with the 45-degree line.\n",
"\n",
"\n",
"Let's define the constants."
@@ -127,7 +128,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "e87f9206",
+ "id": "00705135",
"metadata": {},
"outputs": [],
"source": [
@@ -138,16 +139,16 @@
},
{
"cell_type": "markdown",
- "id": "adad9f3e",
+ "id": "adbd2e69",
"metadata": {},
"source": [
- "Now, we define the function $g$"
+ "Now, we define the function $g$."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "54cc33ce",
+ "id": "75e6c76e",
"metadata": {},
"outputs": [],
"source": [
@@ -157,16 +158,16 @@
},
{
"cell_type": "markdown",
- "id": "c0445260",
+ "id": "bedfd8cb",
"metadata": {},
"source": [
- "Let's plot the 45 degree diagram of $g$"
+ "Let's plot the 45-degree diagram of $g$."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "0d5da377",
+ "id": "10b714f8",
"metadata": {},
"outputs": [],
"source": [
@@ -184,7 +185,7 @@
"\n",
" lb = r'$g(k) = sAk^{\\alpha} + (1 - \\delta)k$'\n",
" ax.plot(xgrid, g_values, lw=2, alpha=0.6, label=lb)\n",
- " ax.plot(xgrid, xgrid, 'k-', lw=1, alpha=0.7, label='45')\n",
+ " ax.plot(xgrid, xgrid, 'k-', lw=1, alpha=0.7, label='$45^{\\circ}$')\n",
"\n",
" if kstar:\n",
" fps = (kstar,)\n",
@@ -213,7 +214,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "35fb287a",
+ "id": "7094ac12",
"metadata": {},
"outputs": [],
"source": [
@@ -222,10 +223,10 @@
},
{
"cell_type": "markdown",
- "id": "3a6d8047",
+ "id": "a6e43aaf",
"metadata": {},
"source": [
- "Suppose, at some $k_t$, the value $g(k_t)$ lies strictly above the 45 degree line.\n",
+ "Suppose, at some $k_t$, the value $g(k_t)$ lies strictly above the 45-degree line.\n",
"\n",
"Then we have $k_{t+1} = g(k_t) > k_t$ and capital per worker rises.\n",
"\n",
@@ -233,7 +234,7 @@
"\n",
"If $g(k_t) = k_t$, then we are at a **steady state** and $k_t$ remains constant.\n",
"\n",
- "(A steady state of the model is a [fixed point](https://en.wikipedia.org/wiki/Fixed_point_(mathematics)) of the mapping $g$.)\n",
+ "(A {ref}`steady state ` of the model is a [fixed point](https://en.wikipedia.org/wiki/Fixed_point_(mathematics)) of the mapping $g$.)\n",
"\n",
"From the shape of the function $g$ in the figure, we see that\n",
"there is a unique steady state in $(0, \\infty)$.\n",
@@ -248,13 +249,13 @@
"\n",
"If initial capital is above this level, then the reverse is true.\n",
"\n",
- "Let's plot the 45 degree diagram to show the $k^*$ in the plot"
+ "Let's plot the 45-degree diagram to show the $k^*$ in the plot."
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "b2c4249f",
+ "id": "7c2f9621",
"metadata": {},
"outputs": [],
"source": [
@@ -264,13 +265,13 @@
},
{
"cell_type": "markdown",
- "id": "a69bbeef",
+ "id": "5fe2c540",
"metadata": {},
"source": [
"From our graphical analysis, it appears that $(k_t)$ converges to $k^*$, regardless of initial capital\n",
"$k_0$.\n",
"\n",
- "This is a form of global stability.\n",
+ "This is a form of {ref}`global stability `.\n",
"\n",
"\n",
"The next figure shows three time paths for capital, from\n",
@@ -284,7 +285,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "ae5a29ba",
+ "id": "5388017c",
"metadata": {},
"outputs": [],
"source": [
@@ -299,7 +300,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "296863fb",
+ "id": "d6f973b5",
"metadata": {},
"outputs": [],
"source": [
@@ -332,7 +333,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "b2290a46",
+ "id": "c0ba5a05",
"metadata": {},
"outputs": [],
"source": [
@@ -341,18 +342,18 @@
},
{
"cell_type": "markdown",
- "id": "bf54f73d",
+ "id": "2d234d3e",
"metadata": {},
"source": [
- "As expected, the time paths in the figure both converge to this value.\n",
+ "As expected, the time paths in the figure all converge to $k^*$.\n",
"\n",
- "## Growth in Continuous Time\n",
+ "## Growth in continuous time\n",
"\n",
- "In this section we investigate a continuous time version of the Solow--Swan\n",
+ "In this section, we investigate a continuous time version of the Solow--Swan\n",
"growth model.\n",
"\n",
"We will see how the smoothing provided by continuous time can\n",
- "simplify analysis.\n",
+ "simplify our analysis.\n",
"\n",
"\n",
"Recall that the discrete time dynamics for capital are\n",
@@ -376,7 +377,7 @@
"```\n",
"\n",
"Our aim is to learn about the evolution of $k_t$ over time,\n",
- "given initial stock $k_0$.\n",
+ "given an initial stock $k_0$.\n",
"\n",
"A **steady state** for {eq}`solowc` is a value $k^*$\n",
"at which capital is unchanging, meaning $k'_t = 0$ or, equivalently,\n",
@@ -393,7 +394,7 @@
"above.\n",
"\n",
"Writing $k'_t = g(k_t)$ with $g(k) =\n",
- "s Ak^\\alpha - \\delta k$, values of $k$ with $g(k) > 0$ imply that $k'_t > 0$, so\n",
+ "s Ak^\\alpha - \\delta k$, values of $k$ with $g(k) > 0$ imply $k'_t > 0$, so\n",
"capital is increasing.\n",
"\n",
"When $g(k) < 0$, the opposite occurs. Once again, high marginal returns to\n",
@@ -406,7 +407,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "27ebad46",
+ "id": "3c3acf45",
"metadata": {},
"outputs": [],
"source": [
@@ -415,7 +416,7 @@
},
{
"cell_type": "markdown",
- "id": "05c97bd9",
+ "id": "7d5b0096",
"metadata": {},
"source": [
"Next we define the function $g$ for growth in continuous time"
@@ -424,7 +425,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "f4366c70",
+ "id": "7dc85bb0",
"metadata": {},
"outputs": [],
"source": [
@@ -435,7 +436,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "35b66d24",
+ "id": "62ea06b6",
"metadata": {},
"outputs": [],
"source": [
@@ -475,7 +476,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "8b1f22d9",
+ "id": "2a95bb75",
"metadata": {},
"outputs": [],
"source": [
@@ -485,7 +486,7 @@
},
{
"cell_type": "markdown",
- "id": "f45b7d6a",
+ "id": "0b83f2f6",
"metadata": {},
"source": [
"This shows global stability heuristically for a fixed parameterization, but\n",
@@ -508,7 +509,7 @@
" x'_t = (1-\\alpha) (sA - \\delta x_t)\n",
"```\n",
"\n",
- "This equation has the exact solution\n",
+ "This equation, which is a [linear ordinary differential equation](https://math.libretexts.org/Bookshelves/Calculus/Calculus_(Guichard)/17%3A_Differential_Equations/17.01%3A_First_Order_Differential_Equations), has the solution\n",
"\n",
"$$\n",
" x_t\n",
@@ -572,7 +573,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "9dfaa123",
+ "id": "755cf1c3",
"metadata": {},
"outputs": [],
"source": [
@@ -584,7 +585,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "815451fc",
+ "id": "ec02a1f1",
"metadata": {},
"outputs": [],
"source": [
@@ -595,7 +596,7 @@
},
{
"cell_type": "markdown",
- "id": "173ae2de",
+ "id": "f80973c2",
"metadata": {},
"source": [
"Let's find the value of $s$ that maximizes $c^*$ using [scipy.optimize.minimize_scalar](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize_scalar.html#scipy.optimize.minimize_scalar).\n",
@@ -605,7 +606,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "add3bc1e",
+ "id": "183230d1",
"metadata": {},
"outputs": [],
"source": [
@@ -615,7 +616,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "0b34830a",
+ "id": "99c42775",
"metadata": {},
"outputs": [],
"source": [
@@ -627,7 +628,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "6e911456",
+ "id": "5201ca76",
"metadata": {},
"outputs": [],
"source": [
@@ -640,7 +641,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "44b9029f",
+ "id": "cb4ad1b3",
"metadata": {},
"outputs": [],
"source": [
@@ -672,7 +673,7 @@
},
{
"cell_type": "markdown",
- "id": "751d8c2e",
+ "id": "6f9db7de",
"metadata": {},
"source": [
"One can also try to solve this mathematically by differentiating $c^*(s)$ and solve for $\\frac{d}{ds}c^*(s)=0$ using [sympy](https://www.sympy.org/en/index.html)."
@@ -681,7 +682,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "1a0d1c8b",
+ "id": "b9a2b15e",
"metadata": {},
"outputs": [],
"source": [
@@ -691,7 +692,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "671f1881",
+ "id": "64542983",
"metadata": {},
"outputs": [],
"source": [
@@ -702,7 +703,7 @@
},
{
"cell_type": "markdown",
- "id": "ed02a43a",
+ "id": "d5dfe2f3",
"metadata": {},
"source": [
"Let's differentiate $c$ and solve using [sympy.solve](https://docs.sympy.org/latest/modules/solvers/solvers.html#sympy.solvers.solvers.solve)"
@@ -711,7 +712,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "596b7347",
+ "id": "24a57529",
"metadata": {},
"outputs": [],
"source": [
@@ -722,7 +723,7 @@
},
{
"cell_type": "markdown",
- "id": "885e3539",
+ "id": "9e87dbfa",
"metadata": {},
"source": [
"Incidentally, the rate of savings which maximizes steady state level of per capita consumption is called the [Golden Rule savings rate](https://en.wikipedia.org/wiki/Golden_Rule_savings_rate).\n",
@@ -776,7 +777,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "d9e48f3e",
+ "id": "ce9c4125",
"metadata": {},
"outputs": [],
"source": [
@@ -792,7 +793,7 @@
},
{
"cell_type": "markdown",
- "id": "dd3dd551",
+ "id": "2f3f2031",
"metadata": {},
"source": [
"Let's define the function *k_next* to find the next value of $k$"
@@ -801,7 +802,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "71ebbdeb",
+ "id": "8a5903b1",
"metadata": {},
"outputs": [],
"source": [
@@ -815,7 +816,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "468053a7",
+ "id": "f6b5a290",
"metadata": {},
"outputs": [],
"source": [
@@ -843,7 +844,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "624087ee",
+ "id": "5d829ffa",
"metadata": {},
"outputs": [],
"source": [
@@ -852,7 +853,7 @@
},
{
"cell_type": "markdown",
- "id": "d80289c6",
+ "id": "d28f351a",
"metadata": {},
"source": [
"```{solution-end}\n",
@@ -861,12 +862,61 @@
}
],
"metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst"
+ }
+ },
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
- }
+ },
+ "source_map": [
+ 10,
+ 25,
+ 28,
+ 119,
+ 123,
+ 127,
+ 130,
+ 134,
+ 175,
+ 177,
+ 204,
+ 207,
+ 223,
+ 232,
+ 259,
+ 261,
+ 321,
+ 323,
+ 327,
+ 332,
+ 366,
+ 369,
+ 451,
+ 457,
+ 461,
+ 466,
+ 470,
+ 476,
+ 483,
+ 508,
+ 512,
+ 516,
+ 520,
+ 524,
+ 528,
+ 577,
+ 586,
+ 590,
+ 598,
+ 620,
+ 622
+ ]
},
"nbformat": 4,
"nbformat_minor": 5
-}
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/solow.md b/book/_build/html/_sources/solow.md
new file mode 100644
index 0000000..0a5160b
--- /dev/null
+++ b/book/_build/html/_sources/solow.md
@@ -0,0 +1,627 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+kernelspec:
+ display_name: Python 3
+ language: python
+ name: python3
+---
+
+(solow)=
+# The Solow-Swan Growth Model
+
+In this lecture we review a famous model due
+to [Robert Solow (1925--2023)](https://en.wikipedia.org/wiki/Robert_Solow) and [Trevor Swan (1918--1989)](https://en.wikipedia.org/wiki/Trevor_Swan).
+
+The model is used to study growth over the long run.
+
+Although the model is simple, it contains some interesting lessons.
+
+
+We will use the following imports.
+
+```{code-cell} ipython3
+import matplotlib.pyplot as plt
+import numpy as np
+```
+
+## The model
+
+In a Solow--Swan economy, agents save a fixed fraction of their current
+incomes.
+
+Savings sustain or increase the stock of capital.
+
+Capital is combined with labor to produce output, which in turn is paid out to
+workers and owners of capital.
+
+To keep things simple, we ignore population and productivity growth.
+
+For each integer $t \geq 0$, output $Y_t$ in period $t$ is given by $Y_t =
+F(K_t, L_t)$, where $K_t$ is capital, $L_t$ is labor and $F$ is an aggregate
+production function.
+
+The function $F$ is assumed to be nonnegative and
+**homogeneous of degree one**, meaning
+that
+
+$$
+ F(\lambda K, \lambda L) = \lambda F(K, L)
+ \quad \text{for all } \lambda \geq 0
+$$
+
+Production functions with this property include
+
+* the **Cobb-Douglas** function $F(K, L) = A K^{\alpha}
+ L^{1-\alpha}$ with $0 \leq \alpha \leq 1$.
+* the **CES** function $F(K, L) = \left\{ a K^\rho + b L^\rho \right\}^{1/\rho}$
+ with $a, b, \rho > 0$.
+
+Here, $\alpha$ is the output elasticity of capital and $\rho$ is a parameter that determines the elasticity of substitution between capital and labor.
+
+We assume a closed economy, so aggregate domestic investment equals aggregate domestic
+saving.
+
+The saving rate is a constant $s$ satisfying $0 \leq s \leq 1$, so that aggregate
+investment and saving both equal $s Y_t$.
+
+Capital depreciates: without replenishing through investment, one unit of capital today
+becomes $1-\delta$ units tomorrow.
+
+Thus,
+
+$$
+ K_{t+1} = s F(K_t, L_t) + (1 - \delta) K_t
+$$
+
+
+Without population growth, $L_t$ equals some constant $L$.
+
+Setting $k_t := K_t / L$ and using homogeneity of degree one now yields
+
+$$
+ k_{t+1}
+ = s \frac{F(K_t, L)}{L} + (1 - \delta) \frac{K_t}{L}
+ = s \frac{F(K_t, L)}{L} + (1 - \delta) k_t
+ = s F(k_t, 1) + (1 - \delta) k_t
+$$
+
+
+With $f(k) := F(k, 1)$, the final expression for capital dynamics is
+
+```{math}
+:label: solow
+ k_{t+1} = g(k_t)
+ \text{ where } g(k) := s f(k) + (1 - \delta) k
+```
+
+Our aim is to learn about the evolution of $k_t$ over time,
+given an exogenous initial capital stock $k_0$.
+
+
+## A graphical perspective
+
+To understand the dynamics of the sequence $(k_t)_{t \geq 0}$ we use a 45-degree diagram.
+
+To do so, we first
+need to specify the functional form for $f$ and assign values to the parameters.
+
+We choose the Cobb--Douglas specification $f(k) = A k^\alpha$ and set $A=2.0$,
+$\alpha=0.3$, $s=0.3$ and $\delta=0.4$.
+
+The function $g$ from {eq}`solow` is then plotted, along with the 45-degree line.
+
+
+Let's define the constants.
+
+```{code-cell} ipython3
+A, s, alpha, delta = 2, 0.3, 0.3, 0.4
+x0 = 0.25
+xmin, xmax = 0, 3
+```
+
+Now, we define the function $g$.
+
+```{code-cell} ipython3
+def g(A, s, alpha, delta, k):
+ return A * s * k**alpha + (1 - delta) * k
+```
+
+Let's plot the 45-degree diagram of $g$.
+
+```{code-cell} ipython3
+def plot45(kstar=None):
+ xgrid = np.linspace(xmin, xmax, 12000)
+
+ fig, ax = plt.subplots()
+
+ ax.set_xlim(xmin, xmax)
+
+ g_values = g(A, s, alpha, delta, xgrid)
+
+ ymin, ymax = np.min(g_values), np.max(g_values)
+ ax.set_ylim(ymin, ymax)
+
+ lb = r'$g(k) = sAk^{\alpha} + (1 - \delta)k$'
+ ax.plot(xgrid, g_values, lw=2, alpha=0.6, label=lb)
+ ax.plot(xgrid, xgrid, 'k-', lw=1, alpha=0.7, label='$45^{\circ}$')
+
+ if kstar:
+ fps = (kstar,)
+
+ ax.plot(fps, fps, 'go', ms=10, alpha=0.6)
+
+ ax.annotate(r'$k^* = (sA / \delta)^{(1/(1-\alpha))}$',
+ xy=(kstar, kstar),
+ xycoords='data',
+ xytext=(-40, -60),
+ textcoords='offset points',
+ fontsize=14,
+ arrowprops=dict(arrowstyle="->"))
+
+ ax.legend(loc='upper left', frameon=False, fontsize=12)
+
+ ax.set_xticks((0, 1, 2, 3))
+ ax.set_yticks((0, 1, 2, 3))
+
+ ax.set_xlabel('$k_t$', fontsize=12)
+ ax.set_ylabel('$k_{t+1}$', fontsize=12)
+
+ plt.show()
+```
+
+```{code-cell} ipython3
+plot45()
+```
+
+Suppose, at some $k_t$, the value $g(k_t)$ lies strictly above the 45-degree line.
+
+Then we have $k_{t+1} = g(k_t) > k_t$ and capital per worker rises.
+
+If $g(k_t) < k_t$ then capital per worker falls.
+
+If $g(k_t) = k_t$, then we are at a **steady state** and $k_t$ remains constant.
+
+(A {ref}`steady state ` of the model is a [fixed point](https://en.wikipedia.org/wiki/Fixed_point_(mathematics)) of the mapping $g$.)
+
+From the shape of the function $g$ in the figure, we see that
+there is a unique steady state in $(0, \infty)$.
+
+It solves $k = s Ak^{\alpha} + (1-\delta)k$ and hence is given by
+
+```{math}
+:label: kstarss
+ k^* := \left( \frac{s A}{\delta} \right)^{1/(1 - \alpha)}
+```
+If initial capital is below $k^*$, then capital increases over time.
+
+If initial capital is above this level, then the reverse is true.
+
+Let's plot the 45-degree diagram to show the $k^*$ in the plot.
+
+```{code-cell} ipython3
+kstar = ((s * A) / delta)**(1/(1 - alpha))
+plot45(kstar)
+```
+
+
+From our graphical analysis, it appears that $(k_t)$ converges to $k^*$, regardless of initial capital
+$k_0$.
+
+This is a form of {ref}`global stability `.
+
+
+The next figure shows three time paths for capital, from
+three distinct initial conditions, under the parameterization listed above.
+
+At this parameterization, $k^* \approx 1.78$.
+
+Let's define the constants and three distinct initial conditions
+
+```{code-cell} ipython3
+A, s, alpha, delta = 2, 0.3, 0.3, 0.4
+x0 = np.array([.25, 1.25, 3.25])
+
+ts_length = 20
+xmin, xmax = 0, ts_length
+ymin, ymax = 0, 3.5
+```
+
+```{code-cell} ipython3
+def simulate_ts(x0_values, ts_length):
+
+ k_star = (s * A / delta)**(1/(1-alpha))
+ fig, ax = plt.subplots(figsize=[11, 5])
+ ax.set_xlim(xmin, xmax)
+ ax.set_ylim(ymin, ymax)
+
+ ts = np.zeros(ts_length)
+
+ # simulate and plot time series
+ for x_init in x0_values:
+ ts[0] = x_init
+ for t in range(1, ts_length):
+ ts[t] = g(A, s, alpha, delta, ts[t-1])
+ ax.plot(np.arange(ts_length), ts, '-o', ms=4, alpha=0.6,
+ label=r'$k_0=%g$' %x_init)
+ ax.plot(np.arange(ts_length), np.full(ts_length,k_star),
+ alpha=0.6, color='red', label=r'$k^*$')
+ ax.legend(fontsize=10)
+
+ ax.set_xlabel(r'$t$', fontsize=14)
+ ax.set_ylabel(r'$k_t$', fontsize=14)
+
+ plt.show()
+```
+
+```{code-cell} ipython3
+simulate_ts(x0, ts_length)
+```
+
+As expected, the time paths in the figure all converge to $k^*$.
+
+## Growth in continuous time
+
+In this section, we investigate a continuous time version of the Solow--Swan
+growth model.
+
+We will see how the smoothing provided by continuous time can
+simplify our analysis.
+
+
+Recall that the discrete time dynamics for capital are
+given by $k_{t+1} = s f(k_t) + (1 - \delta) k_t$.
+
+A simple rearrangement gives the rate of change per unit of time:
+
+$$
+ \Delta k_t = s f(k_t) - \delta k_t
+ \quad \text{where} \quad
+ \Delta k_t := k_{t+1} - k_t
+$$
+
+Taking the time step to zero gives the continuous time limit
+
+```{math}
+:label: solowc
+ k'_t = s f(k_t) - \delta k_t
+ \qquad \text{with} \qquad
+ k'_t := \frac{d}{dt} k_t
+```
+
+Our aim is to learn about the evolution of $k_t$ over time,
+given an initial stock $k_0$.
+
+A **steady state** for {eq}`solowc` is a value $k^*$
+at which capital is unchanging, meaning $k'_t = 0$ or, equivalently,
+$s f(k^*) = \delta k^*$.
+
+We assume
+$f(k) = Ak^\alpha$, so $k^*$ solves
+$s A k^\alpha = \delta k$.
+
+The solution is the same as the discrete time case---see {eq}`kstarss`.
+
+The dynamics are represented in
+the next figure, maintaining the parameterization we used
+above.
+
+Writing $k'_t = g(k_t)$ with $g(k) =
+s Ak^\alpha - \delta k$, values of $k$ with $g(k) > 0$ imply $k'_t > 0$, so
+capital is increasing.
+
+When $g(k) < 0$, the opposite occurs. Once again, high marginal returns to
+savings at low levels of capital combined with low rates of return at high
+levels of capital combine to yield global stability.
+
+To see this in a figure, let's define the constants
+
+```{code-cell} ipython3
+A, s, alpha, delta = 2, 0.3, 0.3, 0.4
+```
+
+Next we define the function $g$ for growth in continuous time
+
+```{code-cell} ipython3
+def g_con(A, s, alpha, delta, k):
+ return A * s * k**alpha - delta * k
+```
+
+```{code-cell} ipython3
+def plot_gcon(kstar=None):
+
+ k_grid = np.linspace(0, 2.8, 10000)
+
+ fig, ax = plt.subplots(figsize=[11, 5])
+ ax.plot(k_grid, g_con(A, s, alpha, delta, k_grid), label='$g(k)$')
+ ax.plot(k_grid, 0 * k_grid, label="$k'=0$")
+
+ if kstar:
+ fps = (kstar,)
+
+ ax.plot(fps, 0, 'go', ms=10, alpha=0.6)
+
+
+ ax.annotate(r'$k^* = (sA / \delta)^{(1/(1-\alpha))}$',
+ xy=(kstar, 0),
+ xycoords='data',
+ xytext=(0, 60),
+ textcoords='offset points',
+ fontsize=12,
+ arrowprops=dict(arrowstyle="->"))
+
+ ax.legend(loc='lower left', fontsize=12)
+
+ ax.set_xlabel("$k$",fontsize=10)
+ ax.set_ylabel("$k'$", fontsize=10)
+
+ ax.set_xticks((0, 1, 2, 3))
+ ax.set_yticks((-0.3, 0, 0.3))
+
+ plt.show()
+```
+
+```{code-cell} ipython3
+kstar = ((s * A) / delta)**(1/(1 - alpha))
+plot_gcon(kstar)
+```
+
+This shows global stability heuristically for a fixed parameterization, but
+how would we show the same thing formally for a continuum of plausible parameters?
+
+In the discrete time case, a neat expression for $k_t$ is hard to obtain.
+
+In continuous time the process is easier: we can obtain a relatively simple
+expression for $k_t$ that specifies the entire path.
+
+The first step is
+to set $x_t := k_t^{1-\alpha}$, so that $x'_t = (1-\alpha) k_t^{-\alpha}
+k'_t$.
+
+Substituting into $k'_t = sAk_t^\alpha - \delta k_t$ leads to the
+linear differential equation
+
+```{math}
+:label: xsolow
+ x'_t = (1-\alpha) (sA - \delta x_t)
+```
+
+This equation, which is a [linear ordinary differential equation](https://math.libretexts.org/Bookshelves/Calculus/Calculus_(Guichard)/17%3A_Differential_Equations/17.01%3A_First_Order_Differential_Equations), has the solution
+
+$$
+ x_t
+ = \left(
+ k_0^{1-\alpha} - \frac{sA}{\delta}
+ \right)
+ \mathrm{e}^{-\delta (1-\alpha) t} +
+ \frac{sA}{\delta}
+$$
+
+(You can confirm that this function $x_t$ satisfies {eq}`xsolow` by
+differentiating it with respect to $t$.)
+
+Converting back to $k_t$ yields
+
+```{math}
+:label: ssivs
+ k_t
+ =
+ \left[
+ \left(
+ k_0^{1-\alpha} - \frac{sA}{\delta}
+ \right)
+ \mathrm{e}^{-\delta (1-\alpha) t} +
+ \frac{sA}{\delta}
+ \right]^{1/(1-\alpha)}
+```
+
+Since $\delta > 0$ and $\alpha \in (0, 1)$, we see immediately that $k_t \to
+k^*$ as $t \to \infty$ independent of $k_0$.
+
+Thus, global stability holds.
+
+## Exercises
+
+```{exercise}
+:label: solow_ex1
+
+Plot per capita consumption $c$ at the steady state, as a function of the savings rate $s$, where $0 \leq s \leq 1$.
+
+Use the Cobb--Douglas specification $f(k) = A k^\alpha$.
+
+Set $A=2.0, \alpha=0.3,$ and $\delta=0.5$
+
+Also, find the approximate value of $s$ that maximizes the $c^*(s)$ and show it in the plot.
+
+```
+
+```{solution-start} solow_ex1
+:class: dropdown
+```
+
+Steady state consumption at savings rate $s$ is given by
+
+
+$$
+ c^*(s) = (1-s)f(k^*) = (1-s)A(k^*)^\alpha
+$$
+
+```{code-cell} ipython3
+A = 2.0
+alpha = 0.3
+delta = 0.5
+```
+
+```{code-cell} ipython3
+s_grid = np.linspace(0, 1, 1000)
+k_star = ((s_grid * A) / delta)**(1/(1 - alpha))
+c_star = (1 - s_grid) * A * k_star ** alpha
+```
+
+Let's find the value of $s$ that maximizes $c^*$ using [scipy.optimize.minimize_scalar](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize_scalar.html#scipy.optimize.minimize_scalar).
+We will use $-c^*(s)$ since `minimize_scalar` finds the minimum value.
+
+```{code-cell} ipython3
+from scipy.optimize import minimize_scalar
+```
+
+```{code-cell} ipython3
+def calc_c_star(s):
+ k = ((s * A) / delta)**(1/(1 - alpha))
+ return - (1 - s) * A * k ** alpha
+```
+
+```{code-cell} ipython3
+return_values = minimize_scalar(calc_c_star, bounds=(0, 1))
+s_star_max = return_values.x
+c_star_max = -return_values.fun
+print(f"Function is maximized at s = {round(s_star_max, 4)}")
+```
+
+```{code-cell} ipython3
+x_s_max = np.array([s_star_max, s_star_max])
+y_s_max = np.array([0, c_star_max])
+
+fig, ax = plt.subplots(figsize=[11, 5])
+
+fps = (c_star_max,)
+
+# Highlight the maximum point with a marker
+ax.plot((s_star_max, ), (c_star_max,), 'go', ms=8, alpha=0.6)
+
+ax.annotate(r'$s^*$',
+ xy=(s_star_max, c_star_max),
+ xycoords='data',
+ xytext=(20, -50),
+ textcoords='offset points',
+ fontsize=12,
+ arrowprops=dict(arrowstyle="->"))
+ax.plot(s_grid, c_star, label=r'$c*(s)$')
+ax.plot(x_s_max, y_s_max, alpha=0.5, ls='dotted')
+ax.set_xlabel(r'$s$')
+ax.set_ylabel(r'$c^*(s)$')
+ax.legend()
+
+plt.show()
+```
+
+One can also try to solve this mathematically by differentiating $c^*(s)$ and solve for $\frac{d}{ds}c^*(s)=0$ using [sympy](https://www.sympy.org/en/index.html).
+
+```{code-cell} ipython3
+from sympy import solve, Symbol
+```
+
+```{code-cell} ipython3
+s_symbol = Symbol('s', real=True)
+k = ((s_symbol * A) / delta)**(1/(1 - alpha))
+c = (1 - s_symbol) * A * k ** alpha
+```
+
+Let's differentiate $c$ and solve using [sympy.solve](https://docs.sympy.org/latest/modules/solvers/solvers.html#sympy.solvers.solvers.solve)
+
+```{code-cell} ipython3
+# Solve using sympy
+s_star = solve(c.diff())[0]
+print(f"s_star = {s_star}")
+```
+
+Incidentally, the rate of savings which maximizes steady state level of per capita consumption is called the [Golden Rule savings rate](https://en.wikipedia.org/wiki/Golden_Rule_savings_rate).
+
+```{solution-end}
+```
+
+```{exercise-start}
+:label: solow_ex2
+```
+**Stochastic Productivity**
+
+To bring the Solow--Swan model closer to data, we need to think about handling
+random fluctuations in aggregate quantities.
+
+Among other things, this will
+eliminate the unrealistic prediction that per-capita output $y_t = A
+k^\alpha_t$ converges to a constant $y^* := A (k^*)^\alpha$.
+
+We shift to discrete time for the following discussion.
+
+One approach is to replace constant productivity with some
+stochastic sequence $(A_t)_{t \geq 1}$.
+
+Dynamics are now
+
+```{math}
+:label: solowran
+ k_{t+1} = s A_{t+1} f(k_t) + (1 - \delta) k_t
+```
+
+We suppose $f$ is Cobb--Douglas and $(A_t)$ is IID and lognormal.
+
+Now the long run convergence obtained in the deterministic case breaks
+down, since the system is hit with new shocks at each point in time.
+
+Consider $A=2.0, s=0.6, \alpha=0.3,$ and $\delta=0.5$
+
+Generate and plot the time series $k_t$.
+
+```{exercise-end}
+```
+
+```{solution-start} solow_ex2
+:class: dropdown
+```
+
+Let's define the constants for lognormal distribution and initial values used for simulation
+
+```{code-cell} ipython3
+# Define the constants
+sig = 0.2
+mu = np.log(2) - sig**2 / 2
+A = 2.0
+s = 0.6
+alpha = 0.3
+delta = 0.5
+x0 = [.25, 3.25] # list of initial values used for simulation
+```
+
+Let's define the function *k_next* to find the next value of $k$
+
+```{code-cell} ipython3
+def lgnorm():
+ return np.exp(mu + sig * np.random.randn())
+
+def k_next(s, alpha, delta, k):
+ return lgnorm() * s * k**alpha + (1 - delta) * k
+```
+
+```{code-cell} ipython3
+def ts_plot(x_values, ts_length):
+ fig, ax = plt.subplots(figsize=[11, 5])
+ ts = np.zeros(ts_length)
+
+ # simulate and plot time series
+ for x_init in x_values:
+ ts[0] = x_init
+ for t in range(1, ts_length):
+ ts[t] = k_next(s, alpha, delta, ts[t-1])
+ ax.plot(np.arange(ts_length), ts, '-o', ms=4,
+ alpha=0.6, label=r'$k_0=%g$' %x_init)
+
+ ax.legend(loc='best', fontsize=10)
+
+ ax.set_xlabel(r'$t$', fontsize=12)
+ ax.set_ylabel(r'$k_t$', fontsize=12)
+
+
+ plt.show()
+```
+
+```{code-cell} ipython3
+ts_plot(x0, 50)
+```
+
+
+
+```{solution-end}
+```
diff --git a/book/_build/html/_sources/status.ipynb b/book/_build/html/_sources/status.ipynb
new file mode 100644
index 0000000..7dba38f
--- /dev/null
+++ b/book/_build/html/_sources/status.ipynb
@@ -0,0 +1,76 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "371835c9",
+ "metadata": {},
+ "source": [
+ "# Execution Statistics\n",
+ "\n",
+ "This table contains the latest execution statistics.\n",
+ "\n",
+ "```{nb-exec-table}\n",
+ "```\n",
+ "\n",
+ "(status:machine-details)=\n",
+ "\n",
+ "These lectures are built on `linux` instances through `github actions`. \n",
+ "\n",
+ "These lectures are using the following python version"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2173ed3e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "!python --version"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b44be3ac",
+ "metadata": {},
+ "source": [
+ "and the following package versions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "db065ee9",
+ "metadata": {
+ "tags": [
+ "hide-output"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "!conda list"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst"
+ }
+ },
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "source_map": [
+ 10,
+ 25,
+ 27,
+ 31
+ ]
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/status.md b/book/_build/html/_sources/status.md
new file mode 100644
index 0000000..3ada25f
--- /dev/null
+++ b/book/_build/html/_sources/status.md
@@ -0,0 +1,34 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+kernelspec:
+ display_name: Python 3
+ language: python
+ name: python3
+---
+
+# Execution Statistics
+
+This table contains the latest execution statistics.
+
+```{nb-exec-table}
+```
+
+(status:machine-details)=
+
+These lectures are built on `linux` instances through `github actions`.
+
+These lectures are using the following python version
+
+```{code-cell} ipython
+!python --version
+```
+
+and the following package versions
+
+```{code-cell} ipython
+:tags: [hide-output]
+!conda list
+```
\ No newline at end of file
diff --git a/book/_build/html/_sources/supply_demand_heterogeneity.ipynb b/book/_build/html/_sources/supply_demand_heterogeneity.ipynb
new file mode 100644
index 0000000..f8fb8c7
--- /dev/null
+++ b/book/_build/html/_sources/supply_demand_heterogeneity.ipynb
@@ -0,0 +1,582 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0a083fdf",
+ "metadata": {},
+ "source": [
+ "(supply_demand_heterogeneity)=\n",
+ "# Market Equilibrium with Heterogeneity\n",
+ "\n",
+ "## Overview\n",
+ "\n",
+ "In the {doc}`previous lecture\n",
+ "`, we studied competitive equilibria in an economy with many goods.\n",
+ "\n",
+ "While the results of the study were informative, we used a strong simplifying assumption: all of the agents in the economy are identical.\n",
+ "\n",
+ "In the real world, households, firms and other economic agents differ from one another along many dimensions.\n",
+ "\n",
+ "In this lecture, we introduce heterogeneity across consumers by allowing their preferences and endowments to differ.\n",
+ "\n",
+ "We will examine competitive equilibrium in this setting.\n",
+ "\n",
+ "We will also show how a \"representative consumer\" can be constructed.\n",
+ "\n",
+ "Here are some imports:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "74d60cdd",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "from scipy.linalg import inv"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7a04536c",
+ "metadata": {},
+ "source": [
+ "## An simple example\n",
+ "\n",
+ "Let's study a simple example of **pure exchange** economy without production.\n",
+ "\n",
+ "There are two consumers who differ in their endowment vectors $e_i$ and their bliss-point vectors $b_i$ for $i=1,2$.\n",
+ "\n",
+ "The total endowment is $e_1 + e_2$.\n",
+ "\n",
+ "A competitive equilibrium requires that\n",
+ "\n",
+ "$$\n",
+ "c_1 + c_2 = e_1 + e_2\n",
+ "$$\n",
+ "\n",
+ "Assume the demand curves\n",
+ "\n",
+ "$$\n",
+ " c_i = (\\Pi^\\top \\Pi )^{-1}(\\Pi^\\top b_i - \\mu_i p )\n",
+ "$$\n",
+ "\n",
+ "Competitive equilibrium then requires that\n",
+ "\n",
+ "$$\n",
+ "e_1 + e_2 =\n",
+ " (\\Pi^\\top \\Pi)^{-1}(\\Pi^\\top (b_1 + b_2) - (\\mu_1 + \\mu_2) p )\n",
+ "$$\n",
+ "\n",
+ "which, after a line or two of linear algebra, implies that\n",
+ "\n",
+ "$$\n",
+ "(\\mu_1 + \\mu_2) p = \\Pi^\\top(b_1+ b_2) - \\Pi^\\top \\Pi (e_1 + e_2)\n",
+ "$$ (eq:old6)\n",
+ "\n",
+ "We can normalize prices by setting $\\mu_1 + \\mu_2 =1$ and then solving\n",
+ "\n",
+ "$$\n",
+ "\\mu_i(p,e) = \\frac{p^\\top (\\Pi^{-1} b_i - e_i)}{p^\\top (\\Pi^\\top \\Pi )^{-1} p}\n",
+ "$$ (eq:old7)\n",
+ "\n",
+ "for $\\mu_i, i = 1,2$.\n",
+ "\n",
+ "```{exercise-start}\n",
+ ":label: sdh_ex1\n",
+ "```\n",
+ "\n",
+ "Show that, up to normalization by a positive scalar, the same competitive equilibrium price vector that you computed in the preceding two-consumer economy would prevail in a single-consumer economy in which a single **representative consumer** has utility function\n",
+ "\n",
+ "$$\n",
+ "-.5 (\\Pi c -b) ^\\top (\\Pi c -b )\n",
+ "$$\n",
+ "\n",
+ "and endowment vector $e$, where\n",
+ "\n",
+ "$$\n",
+ "b = b_1 + b_2\n",
+ "$$\n",
+ "\n",
+ "and\n",
+ "\n",
+ "$$\n",
+ "e = e_1 + e_2 .\n",
+ "$$\n",
+ "\n",
+ "```{exercise-end}\n",
+ "```\n",
+ "\n",
+ "## Pure exchange economy\n",
+ "\n",
+ "Let's further explore a pure exchange economy with $n$ goods and $m$ people.\n",
+ "\n",
+ "### Competitive equilibrium\n",
+ "\n",
+ "We'll compute a competitive equilibrium.\n",
+ "\n",
+ "To compute a competitive equilibrium of a pure exchange economy, we use the fact that\n",
+ "\n",
+ "- Relative prices in a competitive equilibrium are the same as those in a special single person or representative consumer economy with preference $\\Pi$ and $b=\\sum_i b_i$, and endowment $e = \\sum_i e_{i}$.\n",
+ "\n",
+ "We can use the following steps to compute a competitive equilibrium:\n",
+ "\n",
+ "- First we solve the single representative consumer economy by normalizing $\\mu = 1$. Then, we renormalize the price vector by using the first consumption good as a numeraire.\n",
+ "\n",
+ "- Next we use the competitive equilibrium prices to compute each consumer's marginal utility of wealth:\n",
+ "\n",
+ "$$\n",
+ "\\mu_{i}=\\frac{-W_{i}+p^{\\top}\\left(\\Pi^{-1}b_{i}-e_{i}\\right)}{p^{\\top}(\\Pi^{\\top}\\Pi)^{-1}p}$$\n",
+ "\n",
+ "- Finally we compute a competitive equilibrium allocation by using the demand curves:\n",
+ " \n",
+ "$$\n",
+ "c_{i}=\\Pi^{-1}b_{i}-(\\Pi^{\\top}\\Pi)^{-1}\\mu_{i}p \n",
+ "$$\n",
+ "\n",
+ "\n",
+ "### Designing some Python code\n",
+ "\n",
+ "\n",
+ "Below we shall construct a Python class with the following attributes:\n",
+ "\n",
+ " * **Preferences** in the form of\n",
+ "\n",
+ " * an $n \\times n$ positive definite matrix $\\Pi$\n",
+ " * an $n \\times 1$ vector of bliss points $b$\n",
+ "\n",
+ " * **Endowments** in the form of\n",
+ "\n",
+ " * an $n \\times 1$ vector $e$\n",
+ " * a scalar \"wealth\" $W$ with default value $0$\n",
+ "\n",
+ "\n",
+ "The class will include a test to make sure that $b \\gg \\Pi e $ and raise an exception if it is violated\n",
+ "(at some threshold level we'd have to specify).\n",
+ "\n",
+ " * **A Person** in the form of a pair that consists of\n",
+ "\n",
+ " * **Preferences** and **Endowments**\n",
+ "\n",
+ " * **A Pure Exchange Economy** will consist of\n",
+ "\n",
+ " * a collection of $m$ **persons**\n",
+ "\n",
+ " * $m=1$ for our single-agent economy\n",
+ " * $m=2$ for our illustrations of a pure exchange economy\n",
+ "\n",
+ " * an equilibrium price vector $p$ (normalized somehow)\n",
+ " * an equilibrium allocation $c_1, c_2, \\ldots, c_m$ -- a collection of $m$ vectors of dimension $n \\times 1$\n",
+ "\n",
+ "Now let's proceed to code."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a0ffc84b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "class ExchangeEconomy:\n",
+ " def __init__(self, \n",
+ " Π, \n",
+ " bs, \n",
+ " es, \n",
+ " Ws=None, \n",
+ " thres=1.5):\n",
+ " \"\"\"\n",
+ " Set up the environment for an exchange economy\n",
+ "\n",
+ " Args:\n",
+ " Π (np.array): shared matrix of substitution\n",
+ " bs (list): all consumers' bliss points\n",
+ " es (list): all consumers' endowments\n",
+ " Ws (list): all consumers' wealth\n",
+ " thres (float): a threshold set to test b >> Pi e violated\n",
+ " \"\"\"\n",
+ " n, m = Π.shape[0], len(bs)\n",
+ "\n",
+ " # check non-satiation\n",
+ " for b, e in zip(bs, es):\n",
+ " if np.min(b / np.max(Π @ e)) <= thres:\n",
+ " raise Exception('set bliss points further away')\n",
+ "\n",
+ " if Ws == None:\n",
+ " Ws = np.zeros(m)\n",
+ " else:\n",
+ " if sum(Ws) != 0:\n",
+ " raise Exception('invalid wealth distribution')\n",
+ "\n",
+ " self.Π, self.bs, self.es, self.Ws, self.n, self.m = Π, bs, es, Ws, n, m\n",
+ "\n",
+ " def competitive_equilibrium(self):\n",
+ " \"\"\"\n",
+ " Compute the competitive equilibrium prices and allocation\n",
+ " \"\"\"\n",
+ " Π, bs, es, Ws = self.Π, self.bs, self.es, self.Ws\n",
+ " n, m = self.n, self.m\n",
+ " slope_dc = inv(Π.T @ Π)\n",
+ " Π_inv = inv(Π)\n",
+ "\n",
+ " # aggregate\n",
+ " b = sum(bs)\n",
+ " e = sum(es)\n",
+ "\n",
+ " # compute price vector with mu=1 and renormalize\n",
+ " p = Π.T @ b - Π.T @ Π @ e\n",
+ " p = p / p[0]\n",
+ "\n",
+ " # compute marginal utility of wealth\n",
+ " μ_s = []\n",
+ " c_s = []\n",
+ " A = p.T @ slope_dc @ p\n",
+ "\n",
+ " for i in range(m):\n",
+ " μ_i = (-Ws[i] + p.T @ (Π_inv @ bs[i] - es[i])) / A\n",
+ " c_i = Π_inv @ bs[i] - μ_i * slope_dc @ p\n",
+ " μ_s.append(μ_i)\n",
+ " c_s.append(c_i)\n",
+ "\n",
+ " for c_i in c_s:\n",
+ " if any(c_i < 0):\n",
+ " print('allocation: ', c_s)\n",
+ " raise Exception('negative allocation: equilibrium does not exist')\n",
+ "\n",
+ " return p, c_s, μ_s"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "41870199",
+ "metadata": {},
+ "source": [
+ "## Implementation\n",
+ "\n",
+ "Next we use the class ``ExchangeEconomy`` defined above to study \n",
+ "\n",
+ "* a two-person economy without production,\n",
+ "* a dynamic economy, and\n",
+ "* an economy with risk and arrow securities.\n",
+ "\n",
+ "### Two-person economy without production\n",
+ "\n",
+ "Here we study how competitive equilibrium $p, c_1, c_2$ respond to different $b_i$ and $e_i$, $i \\in \\{1, 2\\}$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ff00f579",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Π = np.array([[1, 0],\n",
+ " [0, 1]])\n",
+ "\n",
+ "bs = [np.array([5, 5]), # first consumer's bliss points\n",
+ " np.array([5, 5])] # second consumer's bliss points\n",
+ "\n",
+ "es = [np.array([0, 2]), # first consumer's endowment\n",
+ " np.array([2, 0])] # second consumer's endowment\n",
+ "\n",
+ "EE = ExchangeEconomy(Π, bs, es)\n",
+ "p, c_s, μ_s = EE.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price vector:', p)\n",
+ "print('Competitive equilibrium allocation:', c_s)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "69afb377",
+ "metadata": {},
+ "source": [
+ "What happens if the first consumer likes the first good more and the second consumer likes the second good more?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bc104b8a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "EE.bs = [np.array([6, 5]), # first consumer's bliss points\n",
+ " np.array([5, 6])] # second consumer's bliss points\n",
+ "\n",
+ "p, c_s, μ_s = EE.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price vector:', p)\n",
+ "print('Competitive equilibrium allocation:', c_s)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0222dec9",
+ "metadata": {},
+ "source": [
+ "Let the first consumer be poorer."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3930e0b0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "EE.es = [np.array([0.5, 0.5]), # first consumer's endowment\n",
+ " np.array([1, 1])] # second consumer's endowment\n",
+ "\n",
+ "p, c_s, μ_s = EE.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price vector:', p)\n",
+ "print('Competitive equilibrium allocation:', c_s)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "58014bf9",
+ "metadata": {},
+ "source": [
+ "Now let's construct an autarky (i.e., no-trade) equilibrium."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "28c12cd3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "EE.bs = [np.array([4, 6]), # first consumer's bliss points\n",
+ " np.array([6, 4])] # second consumer's bliss points\n",
+ "\n",
+ "EE.es = [np.array([0, 2]), # first consumer's endowment\n",
+ " np.array([2, 0])] # second consumer's endowment\n",
+ "\n",
+ "p, c_s, μ_s = EE.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price vector:', p)\n",
+ "print('Competitive equilibrium allocation:', c_s)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4fdd95ac",
+ "metadata": {},
+ "source": [
+ "Now let's redistribute endowments before trade."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8a464d38",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bs = [np.array([5, 5]), # first consumer's bliss points\n",
+ " np.array([5, 5])] # second consumer's bliss points\n",
+ "\n",
+ "es = [np.array([1, 1]), # first consumer's endowment\n",
+ " np.array([1, 1])] # second consumer's endowment\n",
+ "\n",
+ "Ws = [0.5, -0.5]\n",
+ "EE_new = ExchangeEconomy(Π, bs, es, Ws)\n",
+ "p, c_s, μ_s = EE_new.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price vector:', p)\n",
+ "print('Competitive equilibrium allocation:', c_s)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c6395a26",
+ "metadata": {},
+ "source": [
+ "### A dynamic economy\n",
+ "\n",
+ "Now let's use the tricks described above to study a dynamic economy, one with two periods."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "11d55efe",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "beta = 0.95\n",
+ "\n",
+ "Π = np.array([[1, 0],\n",
+ " [0, np.sqrt(beta)]])\n",
+ "\n",
+ "bs = [np.array([5, np.sqrt(beta) * 5])]\n",
+ "\n",
+ "es = [np.array([1, 1])]\n",
+ "\n",
+ "EE_DE = ExchangeEconomy(Π, bs, es)\n",
+ "p, c_s, μ_s = EE_DE.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price vector:', p)\n",
+ "print('Competitive equilibrium allocation:', c_s)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a3083f52",
+ "metadata": {},
+ "source": [
+ "### Risk economy with arrow securities\n",
+ "\n",
+ "We use the tricks described above to interpret $c_1, c_2$ as \"Arrow securities\" that are state-contingent claims to consumption goods."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "44b9ec07",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "prob = 0.7\n",
+ "\n",
+ "Π = np.array([[np.sqrt(prob), 0],\n",
+ " [0, np.sqrt(1 - prob)]])\n",
+ "\n",
+ "bs = [np.array([np.sqrt(prob) * 5, np.sqrt(1 - prob) * 5]),\n",
+ " np.array([np.sqrt(prob) * 5, np.sqrt(1 - prob) * 5])]\n",
+ "\n",
+ "es = [np.array([1, 0]),\n",
+ " np.array([0, 1])]\n",
+ "\n",
+ "EE_AS = ExchangeEconomy(Π, bs, es)\n",
+ "p, c_s, μ_s = EE_AS.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price vector:', p)\n",
+ "print('Competitive equilibrium allocation:', c_s)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "eae6a32c",
+ "metadata": {},
+ "source": [
+ "## Deducing a representative consumer\n",
+ "\n",
+ "In the class of multiple consumer economies that we are studying here, it turns out that there\n",
+ "exists a single **representative consumer** whose preferences and endowments can be deduced from lists of preferences and endowments for separate individual consumers.\n",
+ "\n",
+ "Consider a multiple consumer economy with initial distribution of wealth $W_i$ satisfying $\\sum_i W_{i}=0$\n",
+ "\n",
+ "We allow an initial redistribution of wealth.\n",
+ "\n",
+ "We have the following objects\n",
+ "\n",
+ "\n",
+ "- The demand curve:\n",
+ " \n",
+ "$$ \n",
+ "c_{i}=\\Pi^{-1}b_{i}-(\\Pi^{\\top}\\Pi)^{-1}\\mu_{i}p \n",
+ "$$\n",
+ "\n",
+ "- The marginal utility of wealth:\n",
+ " \n",
+ "$$ \n",
+ "\\mu_{i}=\\frac{-W_{i}+p^{\\top}\\left(\\Pi^{-1}b_{i}-e_{i}\\right)}{p^{\\top}(\\Pi^{\\top}\\Pi)^{-1}p}\n",
+ "$$\n",
+ "\n",
+ "- Market clearing:\n",
+ " \n",
+ "$$ \n",
+ "\\sum c_{i}=\\sum e_{i}\n",
+ "$$\n",
+ "\n",
+ "Denote aggregate consumption $\\sum_i c_{i}=c$ and $\\sum_i \\mu_i = \\mu$.\n",
+ "\n",
+ "Market clearing requires\n",
+ "\n",
+ "$$ \n",
+ "\\Pi^{-1}\\left(\\sum_{i}b_{i}\\right)-(\\Pi^{\\top}\\Pi)^{-1}p\\left(\\sum_{i}\\mu_{i}\\right)=\\sum_{i}e_{i}\n",
+ "$$\n",
+ "which, after a few steps, leads to\n",
+ "\n",
+ "$$\n",
+ "p=\\mu^{-1}\\left(\\Pi^{\\top}b-\\Pi^{\\top}\\Pi e\\right)\n",
+ "$$\n",
+ "\n",
+ "where\n",
+ "\n",
+ "$$ \n",
+ "\\mu = \\sum_i\\mu_{i}=\\frac{0 + p^{\\top}\\left(\\Pi^{-1}b-e\\right)}{p^{\\top}(\\Pi^{\\top}\\Pi)^{-1}p}.\n",
+ "$$\n",
+ "\n",
+ "Now consider the representative consumer economy specified above.\n",
+ "\n",
+ "Denote the marginal utility of wealth of the representative consumer by $\\tilde{\\mu}$.\n",
+ "\n",
+ "The demand function is\n",
+ "\n",
+ "$$\n",
+ "c=\\Pi^{-1}b-(\\Pi^{\\top}\\Pi)^{-1}\\tilde{\\mu} p\n",
+ "$$\n",
+ "\n",
+ "Substituting this into the budget constraint gives\n",
+ "\n",
+ "$$\n",
+ "\\tilde{\\mu}=\\frac{p^{\\top}\\left(\\Pi^{-1}b-e\\right)}{p^{\\top}(\\Pi^{\\top}\\Pi)^{-1}p}\n",
+ "$$\n",
+ "\n",
+ "In an equilibrium $c=e$, so\n",
+ "\n",
+ "$$\n",
+ "p=\\tilde{\\mu}^{-1}(\\Pi^{\\top}b-\\Pi^{\\top}\\Pi e)\n",
+ "$$\n",
+ "\n",
+ "Thus, we have verified that, up to the choice of a numeraire in which to express absolute prices, the price \n",
+ "vector in our representative consumer economy is the same as that in an underlying economy with multiple consumers."
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.14.5"
+ }
+ },
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "source_map": [
+ 12,
+ 34,
+ 37,
+ 168,
+ 235,
+ 249,
+ 264,
+ 268,
+ 276,
+ 280,
+ 288,
+ 292,
+ 303,
+ 307,
+ 320,
+ 326,
+ 341,
+ 347,
+ 364
+ ]
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/supply_demand_heterogeneity.md b/book/_build/html/_sources/supply_demand_heterogeneity.md
new file mode 100644
index 0000000..347294b
--- /dev/null
+++ b/book/_build/html/_sources/supply_demand_heterogeneity.md
@@ -0,0 +1,438 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.14.5
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+(supply_demand_heterogeneity)=
+# Market Equilibrium with Heterogeneity
+
+## Overview
+
+In the {doc}`previous lecture
+`, we studied competitive equilibria in an economy with many goods.
+
+While the results of the study were informative, we used a strong simplifying assumption: all of the agents in the economy are identical.
+
+In the real world, households, firms and other economic agents differ from one another along many dimensions.
+
+In this lecture, we introduce heterogeneity across consumers by allowing their preferences and endowments to differ.
+
+We will examine competitive equilibrium in this setting.
+
+We will also show how a "representative consumer" can be constructed.
+
+Here are some imports:
+
+```{code-cell} ipython3
+import numpy as np
+from scipy.linalg import inv
+```
+
+## An simple example
+
+Let's study a simple example of **pure exchange** economy without production.
+
+There are two consumers who differ in their endowment vectors $e_i$ and their bliss-point vectors $b_i$ for $i=1,2$.
+
+The total endowment is $e_1 + e_2$.
+
+A competitive equilibrium requires that
+
+$$
+c_1 + c_2 = e_1 + e_2
+$$
+
+Assume the demand curves
+
+$$
+ c_i = (\Pi^\top \Pi )^{-1}(\Pi^\top b_i - \mu_i p )
+$$
+
+Competitive equilibrium then requires that
+
+$$
+e_1 + e_2 =
+ (\Pi^\top \Pi)^{-1}(\Pi^\top (b_1 + b_2) - (\mu_1 + \mu_2) p )
+$$
+
+which, after a line or two of linear algebra, implies that
+
+$$
+(\mu_1 + \mu_2) p = \Pi^\top(b_1+ b_2) - \Pi^\top \Pi (e_1 + e_2)
+$$ (eq:old6)
+
+We can normalize prices by setting $\mu_1 + \mu_2 =1$ and then solving
+
+$$
+\mu_i(p,e) = \frac{p^\top (\Pi^{-1} b_i - e_i)}{p^\top (\Pi^\top \Pi )^{-1} p}
+$$ (eq:old7)
+
+for $\mu_i, i = 1,2$.
+
+```{exercise-start}
+:label: sdh_ex1
+```
+
+Show that, up to normalization by a positive scalar, the same competitive equilibrium price vector that you computed in the preceding two-consumer economy would prevail in a single-consumer economy in which a single **representative consumer** has utility function
+
+$$
+-.5 (\Pi c -b) ^\top (\Pi c -b )
+$$
+
+and endowment vector $e$, where
+
+$$
+b = b_1 + b_2
+$$
+
+and
+
+$$
+e = e_1 + e_2 .
+$$
+
+```{exercise-end}
+```
+
+## Pure exchange economy
+
+Let's further explore a pure exchange economy with $n$ goods and $m$ people.
+
+### Competitive equilibrium
+
+We'll compute a competitive equilibrium.
+
+To compute a competitive equilibrium of a pure exchange economy, we use the fact that
+
+- Relative prices in a competitive equilibrium are the same as those in a special single person or representative consumer economy with preference $\Pi$ and $b=\sum_i b_i$, and endowment $e = \sum_i e_{i}$.
+
+We can use the following steps to compute a competitive equilibrium:
+
+- First we solve the single representative consumer economy by normalizing $\mu = 1$. Then, we renormalize the price vector by using the first consumption good as a numeraire.
+
+- Next we use the competitive equilibrium prices to compute each consumer's marginal utility of wealth:
+
+$$
+\mu_{i}=\frac{-W_{i}+p^{\top}\left(\Pi^{-1}b_{i}-e_{i}\right)}{p^{\top}(\Pi^{\top}\Pi)^{-1}p}$$
+
+- Finally we compute a competitive equilibrium allocation by using the demand curves:
+
+$$
+c_{i}=\Pi^{-1}b_{i}-(\Pi^{\top}\Pi)^{-1}\mu_{i}p
+$$
+
+
+### Designing some Python code
+
+
+Below we shall construct a Python class with the following attributes:
+
+ * **Preferences** in the form of
+
+ * an $n \times n$ positive definite matrix $\Pi$
+ * an $n \times 1$ vector of bliss points $b$
+
+ * **Endowments** in the form of
+
+ * an $n \times 1$ vector $e$
+ * a scalar "wealth" $W$ with default value $0$
+
+
+The class will include a test to make sure that $b \gg \Pi e $ and raise an exception if it is violated
+(at some threshold level we'd have to specify).
+
+ * **A Person** in the form of a pair that consists of
+
+ * **Preferences** and **Endowments**
+
+ * **A Pure Exchange Economy** will consist of
+
+ * a collection of $m$ **persons**
+
+ * $m=1$ for our single-agent economy
+ * $m=2$ for our illustrations of a pure exchange economy
+
+ * an equilibrium price vector $p$ (normalized somehow)
+ * an equilibrium allocation $c_1, c_2, \ldots, c_m$ -- a collection of $m$ vectors of dimension $n \times 1$
+
+Now let's proceed to code.
+
+```{code-cell} ipython3
+class ExchangeEconomy:
+ def __init__(self,
+ Π,
+ bs,
+ es,
+ Ws=None,
+ thres=1.5):
+ """
+ Set up the environment for an exchange economy
+
+ Args:
+ Π (np.array): shared matrix of substitution
+ bs (list): all consumers' bliss points
+ es (list): all consumers' endowments
+ Ws (list): all consumers' wealth
+ thres (float): a threshold set to test b >> Pi e violated
+ """
+ n, m = Π.shape[0], len(bs)
+
+ # check non-satiation
+ for b, e in zip(bs, es):
+ if np.min(b / np.max(Π @ e)) <= thres:
+ raise Exception('set bliss points further away')
+
+ if Ws == None:
+ Ws = np.zeros(m)
+ else:
+ if sum(Ws) != 0:
+ raise Exception('invalid wealth distribution')
+
+ self.Π, self.bs, self.es, self.Ws, self.n, self.m = Π, bs, es, Ws, n, m
+
+ def competitive_equilibrium(self):
+ """
+ Compute the competitive equilibrium prices and allocation
+ """
+ Π, bs, es, Ws = self.Π, self.bs, self.es, self.Ws
+ n, m = self.n, self.m
+ slope_dc = inv(Π.T @ Π)
+ Π_inv = inv(Π)
+
+ # aggregate
+ b = sum(bs)
+ e = sum(es)
+
+ # compute price vector with mu=1 and renormalize
+ p = Π.T @ b - Π.T @ Π @ e
+ p = p / p[0]
+
+ # compute marginal utility of wealth
+ μ_s = []
+ c_s = []
+ A = p.T @ slope_dc @ p
+
+ for i in range(m):
+ μ_i = (-Ws[i] + p.T @ (Π_inv @ bs[i] - es[i])) / A
+ c_i = Π_inv @ bs[i] - μ_i * slope_dc @ p
+ μ_s.append(μ_i)
+ c_s.append(c_i)
+
+ for c_i in c_s:
+ if any(c_i < 0):
+ print('allocation: ', c_s)
+ raise Exception('negative allocation: equilibrium does not exist')
+
+ return p, c_s, μ_s
+```
+
+## Implementation
+
+Next we use the class ``ExchangeEconomy`` defined above to study
+
+* a two-person economy without production,
+* a dynamic economy, and
+* an economy with risk and arrow securities.
+
+### Two-person economy without production
+
+Here we study how competitive equilibrium $p, c_1, c_2$ respond to different $b_i$ and $e_i$, $i \in \{1, 2\}$.
+
+```{code-cell} ipython3
+Π = np.array([[1, 0],
+ [0, 1]])
+
+bs = [np.array([5, 5]), # first consumer's bliss points
+ np.array([5, 5])] # second consumer's bliss points
+
+es = [np.array([0, 2]), # first consumer's endowment
+ np.array([2, 0])] # second consumer's endowment
+
+EE = ExchangeEconomy(Π, bs, es)
+p, c_s, μ_s = EE.competitive_equilibrium()
+
+print('Competitive equilibrium price vector:', p)
+print('Competitive equilibrium allocation:', c_s)
+```
+
+What happens if the first consumer likes the first good more and the second consumer likes the second good more?
+
+```{code-cell} ipython3
+EE.bs = [np.array([6, 5]), # first consumer's bliss points
+ np.array([5, 6])] # second consumer's bliss points
+
+p, c_s, μ_s = EE.competitive_equilibrium()
+
+print('Competitive equilibrium price vector:', p)
+print('Competitive equilibrium allocation:', c_s)
+```
+
+Let the first consumer be poorer.
+
+```{code-cell} ipython3
+EE.es = [np.array([0.5, 0.5]), # first consumer's endowment
+ np.array([1, 1])] # second consumer's endowment
+
+p, c_s, μ_s = EE.competitive_equilibrium()
+
+print('Competitive equilibrium price vector:', p)
+print('Competitive equilibrium allocation:', c_s)
+```
+
+Now let's construct an autarky (i.e., no-trade) equilibrium.
+
+```{code-cell} ipython3
+EE.bs = [np.array([4, 6]), # first consumer's bliss points
+ np.array([6, 4])] # second consumer's bliss points
+
+EE.es = [np.array([0, 2]), # first consumer's endowment
+ np.array([2, 0])] # second consumer's endowment
+
+p, c_s, μ_s = EE.competitive_equilibrium()
+
+print('Competitive equilibrium price vector:', p)
+print('Competitive equilibrium allocation:', c_s)
+```
+
+Now let's redistribute endowments before trade.
+
+```{code-cell} ipython3
+bs = [np.array([5, 5]), # first consumer's bliss points
+ np.array([5, 5])] # second consumer's bliss points
+
+es = [np.array([1, 1]), # first consumer's endowment
+ np.array([1, 1])] # second consumer's endowment
+
+Ws = [0.5, -0.5]
+EE_new = ExchangeEconomy(Π, bs, es, Ws)
+p, c_s, μ_s = EE_new.competitive_equilibrium()
+
+print('Competitive equilibrium price vector:', p)
+print('Competitive equilibrium allocation:', c_s)
+```
+
+### A dynamic economy
+
+Now let's use the tricks described above to study a dynamic economy, one with two periods.
+
+```{code-cell} ipython3
+beta = 0.95
+
+Π = np.array([[1, 0],
+ [0, np.sqrt(beta)]])
+
+bs = [np.array([5, np.sqrt(beta) * 5])]
+
+es = [np.array([1, 1])]
+
+EE_DE = ExchangeEconomy(Π, bs, es)
+p, c_s, μ_s = EE_DE.competitive_equilibrium()
+
+print('Competitive equilibrium price vector:', p)
+print('Competitive equilibrium allocation:', c_s)
+```
+
+### Risk economy with arrow securities
+
+We use the tricks described above to interpret $c_1, c_2$ as "Arrow securities" that are state-contingent claims to consumption goods.
+
+```{code-cell} ipython3
+prob = 0.7
+
+Π = np.array([[np.sqrt(prob), 0],
+ [0, np.sqrt(1 - prob)]])
+
+bs = [np.array([np.sqrt(prob) * 5, np.sqrt(1 - prob) * 5]),
+ np.array([np.sqrt(prob) * 5, np.sqrt(1 - prob) * 5])]
+
+es = [np.array([1, 0]),
+ np.array([0, 1])]
+
+EE_AS = ExchangeEconomy(Π, bs, es)
+p, c_s, μ_s = EE_AS.competitive_equilibrium()
+
+print('Competitive equilibrium price vector:', p)
+print('Competitive equilibrium allocation:', c_s)
+```
+
+## Deducing a representative consumer
+
+In the class of multiple consumer economies that we are studying here, it turns out that there
+exists a single **representative consumer** whose preferences and endowments can be deduced from lists of preferences and endowments for separate individual consumers.
+
+Consider a multiple consumer economy with initial distribution of wealth $W_i$ satisfying $\sum_i W_{i}=0$
+
+We allow an initial redistribution of wealth.
+
+We have the following objects
+
+
+- The demand curve:
+
+$$
+c_{i}=\Pi^{-1}b_{i}-(\Pi^{\top}\Pi)^{-1}\mu_{i}p
+$$
+
+- The marginal utility of wealth:
+
+$$
+\mu_{i}=\frac{-W_{i}+p^{\top}\left(\Pi^{-1}b_{i}-e_{i}\right)}{p^{\top}(\Pi^{\top}\Pi)^{-1}p}
+$$
+
+- Market clearing:
+
+$$
+\sum c_{i}=\sum e_{i}
+$$
+
+Denote aggregate consumption $\sum_i c_{i}=c$ and $\sum_i \mu_i = \mu$.
+
+Market clearing requires
+
+$$
+\Pi^{-1}\left(\sum_{i}b_{i}\right)-(\Pi^{\top}\Pi)^{-1}p\left(\sum_{i}\mu_{i}\right)=\sum_{i}e_{i}
+$$
+which, after a few steps, leads to
+
+$$
+p=\mu^{-1}\left(\Pi^{\top}b-\Pi^{\top}\Pi e\right)
+$$
+
+where
+
+$$
+\mu = \sum_i\mu_{i}=\frac{0 + p^{\top}\left(\Pi^{-1}b-e\right)}{p^{\top}(\Pi^{\top}\Pi)^{-1}p}.
+$$
+
+Now consider the representative consumer economy specified above.
+
+Denote the marginal utility of wealth of the representative consumer by $\tilde{\mu}$.
+
+The demand function is
+
+$$
+c=\Pi^{-1}b-(\Pi^{\top}\Pi)^{-1}\tilde{\mu} p
+$$
+
+Substituting this into the budget constraint gives
+
+$$
+\tilde{\mu}=\frac{p^{\top}\left(\Pi^{-1}b-e\right)}{p^{\top}(\Pi^{\top}\Pi)^{-1}p}
+$$
+
+In an equilibrium $c=e$, so
+
+$$
+p=\tilde{\mu}^{-1}(\Pi^{\top}b-\Pi^{\top}\Pi e)
+$$
+
+Thus, we have verified that, up to the choice of a numeraire in which to express absolute prices, the price
+vector in our representative consumer economy is the same as that in an underlying economy with multiple consumers.
diff --git a/book/_build/html/_sources/supply_demand_multiple_goods.ipynb b/book/_build/html/_sources/supply_demand_multiple_goods.ipynb
new file mode 100644
index 0000000..610a8dd
--- /dev/null
+++ b/book/_build/html/_sources/supply_demand_multiple_goods.ipynb
@@ -0,0 +1,1504 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "15318565",
+ "metadata": {},
+ "source": [
+ "(supply_demand_multiple_goods)=\n",
+ "# Supply and Demand with Many Goods\n",
+ "\n",
+ "## Overview\n",
+ "\n",
+ "In a {doc}`previous lecture ` we studied supply, demand\n",
+ "and welfare in a market with a single consumption good.\n",
+ "\n",
+ "In this lecture, we study a setting with $n$ goods and $n$ corresponding prices.\n",
+ "\n",
+ "Key infrastructure concepts that we'll encounter in this lecture are\n",
+ "\n",
+ "* inverse demand curves\n",
+ "* marginal utilities of wealth\n",
+ "* inverse supply curves\n",
+ "* consumer surplus\n",
+ "* producer surplus\n",
+ "* social welfare as a sum of consumer and producer surpluses\n",
+ "* competitive equilibrium\n",
+ "\n",
+ "\n",
+ "We will provide a version of the [first fundamental welfare theorem](https://en.wikipedia.org/wiki/Fundamental_theorems_of_welfare_economics), which was formulated by \n",
+ "\n",
+ "* [Leon Walras](https://en.wikipedia.org/wiki/L%C3%A9on_Walras)\n",
+ "* [Francis Ysidro Edgeworth](https://en.wikipedia.org/wiki/Francis_Ysidro_Edgeworth)\n",
+ "* [Vilfredo Pareto](https://en.wikipedia.org/wiki/Vilfredo_Pareto)\n",
+ "\n",
+ "Important extensions to the key ideas were obtained by\n",
+ "\n",
+ "* [Abba Lerner](https://en.wikipedia.org/wiki/Abba_P._Lerner)\n",
+ "* [Harold Hotelling](https://en.wikipedia.org/wiki/Harold_Hotelling)\n",
+ "* [Paul Samuelson](https://en.wikipedia.org/wiki/Paul_Samuelson)\n",
+ "* [Kenneth Arrow](https://en.wikipedia.org/wiki/Kenneth_Arrow) \n",
+ "* [Gerard Debreu](https://en.wikipedia.org/wiki/G%C3%A9rard_Debreu)\n",
+ "\n",
+ "\n",
+ "We shall describe two classic welfare theorems:\n",
+ "\n",
+ "* **first welfare theorem:** for a given distribution of wealth among consumers, a competitive equilibrium allocation of goods solves a social planning problem.\n",
+ "\n",
+ "* **second welfare theorem:** An allocation of goods to consumers that solves a social planning problem can be supported by a competitive equilibrium with an appropriate initial distribution of wealth.\n",
+ "\n",
+ "As usual, we start by importing some Python modules."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "cb1652b5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# import some packages\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "from scipy.linalg import inv"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a4436f92",
+ "metadata": {},
+ "source": [
+ "## Formulas from linear algebra\n",
+ "\n",
+ "We shall apply formulas from linear algebra that\n",
+ "\n",
+ "* differentiate an inner product with respect to each vector\n",
+ "* differentiate a product of a matrix and a vector with respect to the vector\n",
+ "* differentiate a quadratic form in a vector with respect to the vector\n",
+ "\n",
+ "Where $a$ is an $n \\times 1$ vector, $A$ is an $n \\times n$ matrix, and $x$ is an $n \\times 1$ vector:\n",
+ "\n",
+ "$$\n",
+ "\\frac{\\partial a^\\top x }{\\partial x} = \\frac{\\partial x^\\top a }{\\partial x} = a\n",
+ "$$\n",
+ "\n",
+ "$$\n",
+ "\\frac{\\partial A x} {\\partial x} = A\n",
+ "$$\n",
+ "\n",
+ "$$\n",
+ "\\frac{\\partial x^\\top A x}{\\partial x} = (A + A^\\top)x\n",
+ "$$\n",
+ "\n",
+ "## From utility function to demand curve\n",
+ "\n",
+ "Our study of consumers will use the following primitives\n",
+ "\n",
+ "* $\\Pi$ be an $m \\times n$ matrix,\n",
+ "* $b$ be an $m \\times 1$ vector of bliss points,\n",
+ "* $e$ be an $n \\times 1$ vector of endowments, and"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d3130a30",
+ "metadata": {},
+ "source": [
+ "We will analyze endogenous objects $c$ and $p$, where\n",
+ "\n",
+ "* $c$ is an $n \\times 1$ vector of consumptions of various goods,\n",
+ "* $p$ is an $n \\times 1$ vector of prices"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3d9f6be3",
+ "metadata": {},
+ "source": [
+ "The matrix $\\Pi$ describes a consumer's willingness to substitute one good for every other good.\n",
+ "\n",
+ "We assume that $\\Pi$ has linearly independent columns, which implies that $\\Pi^\\top \\Pi$ is a positive definite matrix.\n",
+ "\n",
+ "* it follows that $\\Pi^\\top \\Pi$ has an inverse.\n",
+ "\n",
+ "We shall see below that $(\\Pi^\\top \\Pi)^{-1}$ is a matrix of slopes of (compensated) demand curves for $c$ with respect to a vector of prices:\n",
+ "\n",
+ "$$\n",
+ " \\frac{\\partial c } {\\partial p} = (\\Pi^\\top \\Pi)^{-1}\n",
+ "$$\n",
+ "\n",
+ "A consumer faces $p$ as a price taker and chooses $c$ to maximize the utility function\n",
+ "\n",
+ "$$\n",
+ " - \\frac{1}{2} (\\Pi c -b) ^\\top (\\Pi c -b )\n",
+ "$$ (eq:old0)\n",
+ "\n",
+ "subject to the budget constraint\n",
+ "\n",
+ "$$\n",
+ " p^\\top (c -e ) = 0\n",
+ "$$ (eq:old2)\n",
+ "\n",
+ "We shall specify examples in which $\\Pi$ and $b$ are such that it typically happens that\n",
+ "\n",
+ "$$\n",
+ " \\Pi c \\ll b\n",
+ "$$ (eq:bversusc)\n",
+ "\n",
+ "This means that the consumer has much less of each good than he wants.\n",
+ "\n",
+ "The deviation in {eq}`eq:bversusc` will ultimately assure us that competitive equilibrium prices are positive."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5d9c54dd",
+ "metadata": {},
+ "source": [
+ "### Demand curve implied by constrained utility maximization\n",
+ "\n",
+ "For now, we assume that the budget constraint is {eq}`eq:old2`.\n",
+ "\n",
+ "So we'll be deriving what is known as a **Marshallian** demand curve.\n",
+ "\n",
+ "Our aim is to maximize [](eq:old0) subject to [](eq:old2).\n",
+ "\n",
+ "Form a Lagrangian\n",
+ "\n",
+ "$$ L = - \\frac{1}{2} (\\Pi c -b)^\\top (\\Pi c -b ) + \\mu [p^\\top (e-c)] $$\n",
+ "\n",
+ "where $\\mu$ is a Lagrange multiplier that is often called a **marginal utility of wealth**.\n",
+ "\n",
+ "The consumer chooses $c$ to maximize $L$ and $\\mu$ to minimize it.\n",
+ "\n",
+ "First-order conditions for $c$ are\n",
+ "\n",
+ "$$\n",
+ " \\frac{\\partial L} {\\partial c}\n",
+ " = - \\Pi^\\top \\Pi c + \\Pi^\\top b - \\mu p = 0\n",
+ "$$\n",
+ "\n",
+ "so that, given $\\mu$, the consumer chooses\n",
+ "\n",
+ "$$\n",
+ " c = (\\Pi^\\top \\Pi )^{-1}(\\Pi^\\top b - \\mu p )\n",
+ "$$ (eq:old3)\n",
+ "\n",
+ "Substituting {eq}`eq:old3` into budget constraint {eq}`eq:old2` and solving for $\\mu$ gives\n",
+ "\n",
+ "$$\n",
+ " \\mu(p,e) = \\frac{p^\\top ( \\Pi^\\top \\Pi )^{-1} \\Pi^\\top b - p^\\top e}{p^\\top (\\Pi^\\top \\Pi )^{-1} p}.\n",
+ "$$ (eq:old4)\n",
+ "\n",
+ "Equation {eq}`eq:old4` tells how marginal utility of wealth depends on the endowment vector $e$ and the price vector $p$.\n",
+ "\n",
+ "```{note}\n",
+ "Equation {eq}`eq:old4` is a consequence of imposing that $p^\\top (c - e) = 0$. \n",
+ "\n",
+ "We could instead take $\\mu$ as a parameter and use {eq}`eq:old3` and the budget constraint {eq}`eq:old2p` to solve for wealth. \n",
+ "\n",
+ "Which way we proceed determines whether we are constructing a **Marshallian** or **Hicksian** demand curve.\n",
+ "```\n",
+ "\n",
+ "## Endowment economy\n",
+ "\n",
+ "We now study a pure-exchange economy, or what is sometimes called an endowment economy.\n",
+ "\n",
+ "Consider a single-consumer, multiple-goods economy without production.\n",
+ "\n",
+ "The only source of goods is the single consumer's endowment vector $e$.\n",
+ "\n",
+ "A competitive equilibrium price vector induces the consumer to choose $c=e$.\n",
+ "\n",
+ "This implies that the equilibrium price vector satisfies\n",
+ "\n",
+ "$$\n",
+ "p = \\mu^{-1} (\\Pi^\\top b - \\Pi^\\top \\Pi e)\n",
+ "$$\n",
+ "\n",
+ "In the present case where we have imposed budget constraint in the form {eq}`eq:old2`, we are free to normalize the price vector by setting the marginal utility of wealth $\\mu =1$ (or any other value for that matter).\n",
+ "\n",
+ "This amounts to choosing a common unit (or numeraire) in which prices of all goods are expressed.\n",
+ "\n",
+ "(Doubling all prices will affect neither quantities nor relative prices.)\n",
+ "\n",
+ "We'll set $\\mu=1$.\n",
+ "\n",
+ "```{exercise}\n",
+ ":label: sdm_ex1\n",
+ "\n",
+ "Verify that setting $\\mu=1$ in {eq}`eq:old3` implies that formula {eq}`eq:old4` is satisfied.\n",
+ "\n",
+ "```\n",
+ "\n",
+ "```{exercise}\n",
+ ":label: sdm_ex2\n",
+ "\n",
+ "Verify that setting $\\mu=2$ in {eq}`eq:old3` also implies that formula\n",
+ "{eq}`eq:old4` is satisfied.\n",
+ "\n",
+ "```\n",
+ "\n",
+ "Here is a class that computes competitive equilibria for our economy."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1bf35185",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "class ExchangeEconomy:\n",
+ " \n",
+ " def __init__(self, \n",
+ " Π, \n",
+ " b, \n",
+ " e,\n",
+ " thres=1.5):\n",
+ " \"\"\"\n",
+ " Set up the environment for an exchange economy\n",
+ "\n",
+ " Args:\n",
+ " Π (np.array): shared matrix of substitution\n",
+ " b (list): the consumer's bliss point\n",
+ " e (list): the consumer's endowment\n",
+ " thres (float): a threshold to check p >> Π e condition\n",
+ " \"\"\"\n",
+ "\n",
+ " # check non-satiation\n",
+ " if np.min(b / np.max(Π @ e)) <= thres:\n",
+ " raise Exception('set bliss points further away')\n",
+ "\n",
+ "\n",
+ " self.Π, self.b, self.e = Π, b, e\n",
+ "\n",
+ " \n",
+ " def competitive_equilibrium(self):\n",
+ " \"\"\"\n",
+ " Compute the competitive equilibrium prices and allocation\n",
+ " \"\"\"\n",
+ " Π, b, e = self.Π, self.b, self.e\n",
+ "\n",
+ " # compute price vector with μ=1\n",
+ " p = Π.T @ b - Π.T @ Π @ e\n",
+ " \n",
+ " # compute consumption vector\n",
+ " slope_dc = inv(Π.T @ Π)\n",
+ " Π_inv = inv(Π)\n",
+ " c = Π_inv @ b - slope_dc @ p\n",
+ "\n",
+ " if any(c < 0):\n",
+ " print('allocation: ', c)\n",
+ " raise Exception('negative allocation: equilibrium does not exist')\n",
+ "\n",
+ " return p, c"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6f90ba94",
+ "metadata": {},
+ "source": [
+ "## Digression: Marshallian and Hicksian demand curves\n",
+ "\n",
+ "Sometimes we'll use budget constraint {eq}`eq:old2` in situations in which a consumer's endowment vector $e$ is his **only** source of income.\n",
+ "\n",
+ "Other times we'll instead assume that the consumer has another source of income (positive or negative) and write his budget constraint as\n",
+ "\n",
+ "$$\n",
+ "p ^\\top (c -e ) = w\n",
+ "$$ (eq:old2p)\n",
+ "\n",
+ "where $w$ is measured in \"dollars\" (or some other **numeraire**) and component $p_i$ of the price vector is measured in dollars per unit of good $i$.\n",
+ "\n",
+ "Whether the consumer's budget constraint is {eq}`eq:old2` or {eq}`eq:old2p` and whether we take $w$ as a free parameter or instead as an endogenous variable will affect the consumer's marginal utility of wealth.\n",
+ "\n",
+ "Consequently, how we set $\\mu$ determines whether we are constructing\n",
+ "\n",
+ "* a **Marshallian** demand curve, as when we use {eq}`eq:old2` and solve for $\\mu$ using equation {eq}`eq:old4` above, or\n",
+ "* a **Hicksian** demand curve, as when we treat $\\mu$ as a fixed parameter and solve for $w$ from {eq}`eq:old2p`.\n",
+ "\n",
+ "Marshallian and Hicksian demand curves contemplate different mental experiments:\n",
+ "\n",
+ "For a Marshallian demand curve, hypothetical changes in a price vector have both **substitution** and **income** effects\n",
+ "\n",
+ "* income effects are consequences of changes in $p^\\top e$ associated with the change in the price vector\n",
+ "\n",
+ "For a Hicksian demand curve, hypothetical price vector changes have only **substitution** effects\n",
+ "\n",
+ "* changes in the price vector leave the $p^\\top e + w$ unaltered because we freeze $\\mu$ and solve for $w$\n",
+ "\n",
+ "Sometimes a Hicksian demand curve is called a **compensated** demand curve in order to emphasize that, to disarm the income (or wealth) effect associated with a price change, the consumer's wealth $w$ is adjusted.\n",
+ "\n",
+ "We'll discuss these distinct demand curves more below."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a1fc0e9d",
+ "metadata": {},
+ "source": [
+ "## Dynamics and risk as special cases\n",
+ "\n",
+ "Special cases of our $n$-good pure exchange model can be created to represent\n",
+ "\n",
+ "* **dynamics** --- by putting different dates on different commodities\n",
+ "* **risk** --- by interpreting delivery of goods as being contingent on states of the world whose realizations are described by a *known probability distribution*\n",
+ "\n",
+ "Let's illustrate how.\n",
+ "\n",
+ "### Dynamics\n",
+ "\n",
+ "Suppose that we want to represent a utility function\n",
+ "\n",
+ "$$\n",
+ " - \\frac{1}{2} [(c_1 - b_1)^2 + \\beta (c_2 - b_2)^2]\n",
+ "$$\n",
+ "\n",
+ "where $\\beta \\in (0,1)$ is a discount factor, $c_1$ is consumption at time $1$ and $c_2$ is consumption at time 2.\n",
+ "\n",
+ "To capture this with our quadratic utility function {eq}`eq:old0`, set\n",
+ "\n",
+ "$$\n",
+ "\\Pi = \\begin{bmatrix} 1 & 0 \\cr\n",
+ " 0 & \\sqrt{\\beta} \\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "$$\n",
+ "e = \\begin{bmatrix} e_1 \\cr e_2 \\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "and\n",
+ "\n",
+ "$$\n",
+ "b = \\begin{bmatrix} b_1 \\cr \\sqrt{\\beta} b_2\n",
+ "\\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "The budget constraint {eq}`eq:old2` becomes\n",
+ "\n",
+ "$$\n",
+ "p_1 c_1 + p_2 c_2 = p_1 e_1 + p_2 e_2\n",
+ "$$\n",
+ "\n",
+ "The left side is the **discounted present value** of consumption.\n",
+ "\n",
+ "The right side is the **discounted present value** of the consumer's endowment.\n",
+ "\n",
+ "The relative price $\\frac{p_1}{p_2}$ has units of time $2$ goods per unit of time $1$ goods.\n",
+ "\n",
+ "Consequently, \n",
+ "\n",
+ "$$\n",
+ " (1+r) := R := \\frac{p_1}{p_2}\n",
+ "$$ \n",
+ "\n",
+ "is the **gross interest rate** and $r$ is the **net interest rate**.\n",
+ "\n",
+ "Here is an example."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "fb1040c4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "beta = 0.95\n",
+ "\n",
+ "Π = np.array([[1, 0],\n",
+ " [0, np.sqrt(beta)]])\n",
+ "\n",
+ "b = np.array([5, np.sqrt(beta) * 5])\n",
+ "\n",
+ "e = np.array([1, 1])\n",
+ "\n",
+ "dynamics = ExchangeEconomy(Π, b, e)\n",
+ "p, c = dynamics.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price vector:', p)\n",
+ "print('Competitive equilibrium allocation:', c)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3c5bc5d6",
+ "metadata": {},
+ "source": [
+ "### Risk and state-contingent claims\n",
+ "\n",
+ "We study risk in the context of a **static** environment, meaning that there is only one period.\n",
+ "\n",
+ "By **risk** we mean that an outcome is not known in advance, but that it is governed by a known probability distribution.\n",
+ "\n",
+ "As an example, our consumer confronts **risk** means in particular that\n",
+ "\n",
+ " * there are two states of nature, $1$ and $2$.\n",
+ "\n",
+ " * the consumer knows that the probability that state $1$ occurs is $\\lambda$.\n",
+ "\n",
+ " * the consumer knows that the probability that state $2$ occurs is $(1-\\lambda)$.\n",
+ "\n",
+ "Before the outcome is realized, the consumer's **expected utility** is\n",
+ "\n",
+ "$$\n",
+ "- \\frac{1}{2} [\\lambda (c_1 - b_1)^2 + (1-\\lambda)(c_2 - b_2)^2]\n",
+ "$$\n",
+ "\n",
+ "where\n",
+ "\n",
+ "* $c_1$ is consumption in state $1$\n",
+ "* $c_2$ is consumption in state $2$\n",
+ "\n",
+ "To capture these preferences we set\n",
+ "\n",
+ "$$\n",
+ "\\Pi = \\begin{bmatrix} \\sqrt{\\lambda} & 0 \\cr\n",
+ " 0 & \\sqrt{1-\\lambda} \\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "$$\n",
+ "e = \\begin{bmatrix} e_1 \\cr e_2 \\end{bmatrix}\n",
+ "$$"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "363fb08b",
+ "metadata": {},
+ "source": [
+ "$$\n",
+ "b = \\begin{bmatrix} \\sqrt{\\lambda}b_1 \\cr \\sqrt{1-\\lambda}b_2 \\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "A consumer's endowment vector is\n",
+ "\n",
+ "$$\n",
+ "c = \\begin{bmatrix} c_1 \\cr c_2 \\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "A price vector is\n",
+ "\n",
+ "$$\n",
+ "p = \\begin{bmatrix} p_1 \\cr p_2 \\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "where $p_i$ is the price of one unit of consumption in state $i \\in \\{1, 2\\}$.\n",
+ "\n",
+ "The state-contingent goods being traded are often called **Arrow securities**.\n",
+ "\n",
+ "Before the random state of the world $i$ is realized, the consumer sells his/her state-contingent endowment bundle and purchases a state-contingent consumption bundle.\n",
+ "\n",
+ "Trading such state-contingent goods is one way economists often model **insurance**."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "bcb7548b",
+ "metadata": {},
+ "source": [
+ "We use the tricks described above to interpret $c_1, c_2$ as \"Arrow securities\" that are state-contingent claims to consumption goods."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f2a5e02b",
+ "metadata": {},
+ "source": [
+ "Here is an instance of the risk economy:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "efcc5f01",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "prob = 0.2\n",
+ "\n",
+ "Π = np.array([[np.sqrt(prob), 0],\n",
+ " [0, np.sqrt(1 - prob)]])\n",
+ "\n",
+ "b = np.array([np.sqrt(prob) * 5, np.sqrt(1 - prob) * 5])\n",
+ "\n",
+ "e = np.array([1, 1])\n",
+ "\n",
+ "risk = ExchangeEconomy(Π, b, e)\n",
+ "p, c = risk.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price vector:', p)\n",
+ "print('Competitive equilibrium allocation:', c)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "cb369781",
+ "metadata": {},
+ "source": [
+ "```{exercise}\n",
+ ":label: sdm_ex3\n",
+ "\n",
+ "Consider the instance above.\n",
+ "\n",
+ "Please numerically study how each of the following cases affects the equilibrium prices and allocations:\n",
+ "\n",
+ "* the consumer gets poorer,\n",
+ "* they like the first good more, or\n",
+ "* the probability that state $1$ occurs is higher.\n",
+ "\n",
+ "Hints. For each case choose some parameter $e, b, \\text{ or } \\lambda$ different from the instance.\n",
+ "\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "98db78cb",
+ "metadata": {},
+ "source": [
+ "```{solution-start} sdm_ex3\n",
+ ":class: dropdown\n",
+ "```\n",
+ "\n",
+ "First consider when the consumer is poorer.\n",
+ "\n",
+ "Here we just decrease the endowment."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4515c364",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "risk.e = np.array([0.5, 0.5])\n",
+ "\n",
+ "p, c = risk.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price vector:', p)\n",
+ "print('Competitive equilibrium allocation:', c)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2df35f89",
+ "metadata": {},
+ "source": [
+ "If the consumer likes the first (or second) good more, then we can set a larger bliss value for good 1."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2533a676",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "risk.b = np.array([np.sqrt(prob) * 6, np.sqrt(1 - prob) * 5])\n",
+ "p, c = risk.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price vector:', p)\n",
+ "print('Competitive equilibrium allocation:', c)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b33d54fa",
+ "metadata": {},
+ "source": [
+ "Increase the probability that state $1$ occurs."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b0cf972b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "prob = 0.8\n",
+ "\n",
+ "Π = np.array([[np.sqrt(prob), 0],\n",
+ " [0, np.sqrt(1 - prob)]])\n",
+ "\n",
+ "b = np.array([np.sqrt(prob) * 5, np.sqrt(1 - prob) * 5])\n",
+ "\n",
+ "e = np.array([1, 1])\n",
+ "\n",
+ "risk = ExchangeEconomy(Π, b, e)\n",
+ "p, c = risk.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price vector:', p)\n",
+ "print('Competitive equilibrium allocation:', c)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7f154cb2",
+ "metadata": {},
+ "source": [
+ "```{solution-end}\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9fc3a565",
+ "metadata": {},
+ "source": [
+ "## Economies with endogenous supplies of goods\n",
+ "\n",
+ "Up to now we have described a pure exchange economy in which endowments of goods are exogenous, meaning that they are taken as given from outside the model.\n",
+ "\n",
+ "### Supply curve of a competitive firm\n",
+ "\n",
+ "A competitive firm that can produce goods takes a price vector $p$ as given and chooses a quantity $q$\n",
+ "to maximize total revenue minus total costs.\n",
+ "\n",
+ "The firm's total revenue equals $p^\\top q$ and its total cost equals $C(q)$ where $C(q)$ is a total cost function\n",
+ "\n",
+ "$$\n",
+ "C(q) = h ^\\top q + \\frac{1}{2} q^\\top J q\n",
+ "$$\n",
+ "\n",
+ "\n",
+ "and $J$ is a positive definite matrix.\n",
+ "\n",
+ "\n",
+ "So the firm's profits are\n",
+ "\n",
+ "$$\n",
+ "p^\\top q - C(q)\n",
+ "$$ (eq:compprofits)\n",
+ "\n",
+ "\n",
+ "\n",
+ "An $n\\times 1$ vector of **marginal costs** is\n",
+ "\n",
+ "$$\n",
+ "\\frac{\\partial C(q)}{\\partial q} = h + H q\n",
+ "$$\n",
+ "\n",
+ "where\n",
+ "\n",
+ "$$\n",
+ "H = \\frac{1}{2} (J + J^\\top)\n",
+ "$$\n",
+ "\n",
+ "The firm maximizes total profits by setting **marginal revenue to marginal costs**.\n",
+ "\n",
+ "An $n \\times 1$ vector of marginal revenues for the price-taking firm is $\\frac{\\partial p^\\top q}\n",
+ "{\\partial q} = p $.\n",
+ "\n",
+ "So **price equals marginal revenue** for our price-taking competitive firm.\n",
+ "\n",
+ "This leads to the following **inverse supply curve** for the competitive firm:\n",
+ "\n",
+ "\n",
+ "$$\n",
+ "p = h + H q\n",
+ "$$\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "### Competitive equilibrium\n",
+ "\n",
+ "\n",
+ "To compute a competitive equilibrium for a production economy where demand curve is pinned down by the marginal utility of wealth $\\mu$, we first compute an allocation by solving a planning problem.\n",
+ "\n",
+ "Then we compute the equilibrium price vector using the inverse demand or supply curve.\n",
+ "\n",
+ "#### $\\mu=1$ warmup\n",
+ "\n",
+ "As a special case, let's pin down a demand curve by setting the marginal utility of wealth $\\mu =1$.\n",
+ "\n",
+ "Equating supply price to demand price and letting $q=c$ we get\n",
+ "\n",
+ "$$\n",
+ "p = h + H c = \\Pi^\\top b - \\Pi^\\top \\Pi c ,\n",
+ "$$\n",
+ "\n",
+ "which implies the equilibrium quantity vector\n",
+ "\n",
+ "$$\n",
+ "c = (\\Pi^\\top \\Pi + H )^{-1} ( \\Pi^\\top b - h)\n",
+ "$$ (eq:old5)\n",
+ "\n",
+ "This equation is the counterpart of equilibrium quantity {eq}`eq:old1` for the scalar $n=1$ model with which we began.\n",
+ "\n",
+ "#### General $\\mu\\neq 1$ case\n",
+ "\n",
+ "Now let's extend the preceding analysis to a more\n",
+ "general case by allowing $\\mu \\neq 1$.\n",
+ "\n",
+ "Then the inverse demand curve is\n",
+ "\n",
+ "$$\n",
+ "p = \\mu^{-1} [\\Pi^\\top b - \\Pi^\\top \\Pi c]\n",
+ "$$ (eq:old5pa)\n",
+ "\n",
+ "Equating this to the inverse supply curve, letting $q=c$ and solving\n",
+ "for $c$ gives\n",
+ "\n",
+ "$$\n",
+ "c = [\\Pi^\\top \\Pi + \\mu H]^{-1} [ \\Pi^\\top b - \\mu h]\n",
+ "$$ (eq:old5p)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f12b73be",
+ "metadata": {},
+ "source": [
+ "### Implementation\n",
+ "\n",
+ "A Production Economy will consist of\n",
+ "\n",
+ "* a single **person** that we'll interpret as a representative consumer\n",
+ "* a single set of **production costs**\n",
+ "* a multiplier $\\mu$ that weights \"consumers\" versus \"producers\" in a planner's welfare function, as described above in the main text\n",
+ "* an $n \\times 1$ vector $p$ of competitive equilibrium prices\n",
+ "* an $n \\times 1$ vector $c$ of competitive equilibrium quantities\n",
+ "* **consumer surplus**\n",
+ "* **producer surplus**\n",
+ "\n",
+ "Here we define a class ``ProductionEconomy``."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5a995758",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "class ProductionEconomy:\n",
+ " \n",
+ " def __init__(self, \n",
+ " Π, \n",
+ " b, \n",
+ " h, \n",
+ " J, \n",
+ " μ):\n",
+ " \"\"\"\n",
+ " Set up the environment for a production economy\n",
+ "\n",
+ " Args:\n",
+ " Π (np.ndarray): matrix of substitution\n",
+ " b (np.array): bliss points\n",
+ " h (np.array): h in cost func\n",
+ " J (np.ndarray): J in cost func\n",
+ " μ (float): welfare weight of the corresponding planning problem\n",
+ " \"\"\"\n",
+ " self.n = len(b)\n",
+ " self.Π, self.b, self.h, self.J, self.μ = Π, b, h, J, μ\n",
+ " \n",
+ " def competitive_equilibrium(self):\n",
+ " \"\"\"\n",
+ " Compute a competitive equilibrium of the production economy\n",
+ " \"\"\"\n",
+ " Π, b, h, μ, J = self.Π, self.b, self.h, self.μ, self.J\n",
+ " H = .5 * (J + J.T)\n",
+ "\n",
+ " # allocation\n",
+ " c = inv(Π.T @ Π + μ * H) @ (Π.T @ b - μ * h)\n",
+ "\n",
+ " # price\n",
+ " p = 1 / μ * (Π.T @ b - Π.T @ Π @ c)\n",
+ "\n",
+ " # check non-satiation\n",
+ " if any(Π @ c - b >= 0):\n",
+ " raise Exception('invalid result: set bliss points further away')\n",
+ "\n",
+ " return c, p\n",
+ "\n",
+ " def compute_surplus(self):\n",
+ " \"\"\"\n",
+ " Compute consumer and producer surplus for single good case\n",
+ " \"\"\"\n",
+ " if self.n != 1:\n",
+ " raise Exception('not single good')\n",
+ " h, J, Π, b, μ = self.h.item(), self.J.item(), self.Π.item(), self.b.item(), self.μ\n",
+ " H = J\n",
+ "\n",
+ " # supply/demand curve coefficients\n",
+ " s0, s1 = h, H\n",
+ " d0, d1 = 1 / μ * Π * b, 1 / μ * Π**2\n",
+ "\n",
+ " # competitive equilibrium\n",
+ " c, p = self.competitive_equilibrium()\n",
+ "\n",
+ " # calculate surplus\n",
+ " c_surplus = d0 * c - .5 * d1 * c**2 - p * c\n",
+ " p_surplus = p * c - s0 * c - .5 * s1 * c**2\n",
+ "\n",
+ " return c_surplus, p_surplus"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "10fbde83",
+ "metadata": {},
+ "source": [
+ "Then define a function that plots demand and supply curves and labels surpluses and equilibrium."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "0601aa5b",
+ "metadata": {
+ "tags": [
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "def plot_competitive_equilibrium(PE):\n",
+ " \"\"\"\n",
+ " Plot demand and supply curves, producer/consumer surpluses, and equilibrium for\n",
+ " a single good production economy\n",
+ "\n",
+ " Args:\n",
+ " PE (class): A initialized production economy class\n",
+ " \"\"\"\n",
+ " # get singleton value\n",
+ " J, h, Π, b, μ = PE.J.item(), PE.h.item(), PE.Π.item(), PE.b.item(), PE.μ\n",
+ " H = J\n",
+ "\n",
+ " # compute competitive equilibrium\n",
+ " c, p = PE.competitive_equilibrium()\n",
+ " c, p = c.item(), p.item()\n",
+ "\n",
+ " # inverse supply/demand curve\n",
+ " supply_inv = lambda x: h + H * x\n",
+ " demand_inv = lambda x: 1 / μ * (Π * b - Π * Π * x)\n",
+ "\n",
+ " xs = np.linspace(0, 2 * c, 100)\n",
+ " ps = np.ones(100) * p\n",
+ " supply_curve = supply_inv(xs)\n",
+ " demand_curve = demand_inv(xs)\n",
+ "\n",
+ " # plot\n",
+ " plt.figure()\n",
+ " plt.plot(xs, supply_curve, label='Supply', color='#020060')\n",
+ " plt.plot(xs, demand_curve, label='Demand', color='#600001')\n",
+ "\n",
+ " plt.fill_between(xs[xs <= c], demand_curve[xs <= c], ps[xs <= c], label='Consumer surplus', color='#EED1CF')\n",
+ " plt.fill_between(xs[xs <= c], supply_curve[xs <= c], ps[xs <= c], label='Producer surplus', color='#E6E6F5')\n",
+ "\n",
+ " plt.vlines(c, 0, p, linestyle=\"dashed\", color='black', alpha=0.7)\n",
+ " plt.hlines(p, 0, c, linestyle=\"dashed\", color='black', alpha=0.7)\n",
+ " plt.scatter(c, p, zorder=10, label='Competitive equilibrium', color='#600001')\n",
+ "\n",
+ " plt.legend(loc='upper right')\n",
+ " plt.margins(x=0, y=0)\n",
+ " plt.ylim(0)\n",
+ " plt.xlabel('Quantity')\n",
+ " plt.ylabel('Price')\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c58ab1aa",
+ "metadata": {},
+ "source": [
+ "#### Example: single agent with one good and production\n",
+ "\n",
+ "Now let's construct an example of a production economy with one good.\n",
+ "\n",
+ "To do this we\n",
+ "\n",
+ " * specify a single **person** and a **cost curve** in a way that let's us replicate the simple single-good supply demand example with which we started\n",
+ "\n",
+ " * compute equilibrium $p$ and $c$ and consumer and producer surpluses\n",
+ "\n",
+ " * draw graphs of both surpluses\n",
+ "\n",
+ " * do experiments in which we shift $b$ and watch what happens to $p, c$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e625a4f4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Π = np.array([[1]]) # the matrix now is a singleton\n",
+ "b = np.array([10])\n",
+ "h = np.array([0.5])\n",
+ "J = np.array([[1]])\n",
+ "μ = 1\n",
+ "\n",
+ "PE = ProductionEconomy(Π, b, h, J, μ)\n",
+ "c, p = PE.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price:', p.item())\n",
+ "print('Competitive equilibrium allocation:', c.item())\n",
+ "\n",
+ "# plot\n",
+ "plot_competitive_equilibrium(PE)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c13f9a16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "c_surplus, p_surplus = PE.compute_surplus()\n",
+ "\n",
+ "print('Consumer surplus:', c_surplus.item())\n",
+ "print('Producer surplus:', p_surplus.item())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c992857b",
+ "metadata": {},
+ "source": [
+ "Let's give the consumer a lower welfare weight by raising $\\mu$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6ee8ee2d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "PE.μ = 2\n",
+ "c, p = PE.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price:', p.item())\n",
+ "print('Competitive equilibrium allocation:', c.item())\n",
+ "\n",
+ "# plot\n",
+ "plot_competitive_equilibrium(PE)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "df32f68b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "c_surplus, p_surplus = PE.compute_surplus()\n",
+ "\n",
+ "print('Consumer surplus:', c_surplus.item())\n",
+ "print('Producer surplus:', p_surplus.item())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0334d0f8",
+ "metadata": {},
+ "source": [
+ "Now we change the bliss point so that the consumer derives more utility from consumption."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9ed4ea1a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "PE.μ = 1\n",
+ "PE.b = PE.b * 1.5\n",
+ "c, p = PE.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price:', p.item())\n",
+ "print('Competitive equilibrium allocation:', c.item())\n",
+ "\n",
+ "# plot\n",
+ "plot_competitive_equilibrium(PE)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5eb74843",
+ "metadata": {},
+ "source": [
+ "This raises both the equilibrium price and quantity.\n",
+ "\n",
+ "\n",
+ "#### Example: single agent two-good economy with production\n",
+ "\n",
+ " * we'll do some experiments like those above\n",
+ "\n",
+ " * we can do experiments with a **diagonal** $\\Pi$ and also with a **non-diagonal** $\\Pi$ matrices to study how cross-slopes affect responses of $p$ and $c$ to various shifts in $b$ (TODO)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a84f106d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Π = np.array([[1, 0],\n",
+ " [0, 1]])\n",
+ "\n",
+ "b = np.array([10, 10])\n",
+ "\n",
+ "h = np.array([0.5, 0.5])\n",
+ "\n",
+ "J = np.array([[1, 0.5],\n",
+ " [0.5, 1]])\n",
+ "μ = 1\n",
+ "\n",
+ "PE = ProductionEconomy(Π, b, h, J, μ)\n",
+ "c, p = PE.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price:', p)\n",
+ "print('Competitive equilibrium allocation:', c)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b16d77bf",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "PE.b = np.array([12, 10])\n",
+ "\n",
+ "c, p = PE.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price:', p)\n",
+ "print('Competitive equilibrium allocation:', c)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d8b39507",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "PE.Π = np.array([[1, 0.5],\n",
+ " [0.5, 1]])\n",
+ "\n",
+ "PE.b = np.array([10, 10])\n",
+ "\n",
+ "c, p = PE.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price:', p)\n",
+ "print('Competitive equilibrium allocation:', c)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7a085c31",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "PE.b = np.array([12, 10])\n",
+ "c, p = PE.competitive_equilibrium()\n",
+ "\n",
+ "print('Competitive equilibrium price:', p)\n",
+ "print('Competitive equilibrium allocation:', c)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "fab7e4d4",
+ "metadata": {},
+ "source": [
+ "### Digression: a supplier who is a monopolist\n",
+ "\n",
+ "A competitive firm is a **price-taker** who regards the price and therefore its marginal revenue as being beyond its control.\n",
+ "\n",
+ "A monopolist knows that it has no competition and can influence the price and its marginal revenue by\n",
+ "setting quantity.\n",
+ "\n",
+ "A monopolist takes a **demand curve** and not the **price** as beyond its control.\n",
+ "\n",
+ "Thus, instead of being a price-taker, a monopolist sets prices to maximize profits subject to the inverse demand curve\n",
+ "{eq}`eq:old5pa`.\n",
+ "\n",
+ "So the monopolist's total profits as a function of its output $q$ is\n",
+ "\n",
+ "$$\n",
+ "[\\mu^{-1} \\Pi^\\top (b - \\Pi q)]^\\top q - h^\\top q - \\frac{1}{2} q^\\top J q\n",
+ "$$ (eq:monopprof)\n",
+ "\n",
+ "After finding\n",
+ "first-order necessary conditions for maximizing monopoly profits with respect to $q$\n",
+ "and solving them for $q$, we find that the monopolist sets\n",
+ "\n",
+ "$$\n",
+ "q = (H + 2 \\mu^{-1} \\Pi^\\top \\Pi)^{-1} (\\mu^{-1} \\Pi^\\top b - h)\n",
+ "$$ (eq:qmonop)\n",
+ "\n",
+ "We'll soon see that a monopolist sets a **lower output** $q$ than does either a\n",
+ "\n",
+ " * planner who chooses $q$ to maximize social welfare\n",
+ "\n",
+ " * a competitive equilibrium\n",
+ "\n",
+ "\n",
+ "\n",
+ "```{exercise}\n",
+ ":label: sdm_ex4\n",
+ "\n",
+ "Please verify the monopolist's supply curve {eq}`eq:qmonop`.\n",
+ "\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "14df1354",
+ "metadata": {},
+ "source": [
+ "### A monopolist\n",
+ "\n",
+ "Let's consider a monopolist supplier.\n",
+ "\n",
+ "We have included a method in our `ProductionEconomy` class to compute an equilibrium price and allocation when the supplier is a monopolist.\n",
+ "\n",
+ "Since the supplier now has the price-setting power\n",
+ "\n",
+ "- we first compute the optimal quantity that solves the monopolist's profit maximization problem.\n",
+ "- Then we back out an equilibrium price from the consumer's inverse demand curve.\n",
+ "\n",
+ "Next, we use a graph for the single good case to illustrate the difference between a competitive equilibrium and an equilibrium with a monopolist supplier.\n",
+ "\n",
+ "Recall that in a competitive equilibrium, a price-taking supplier equates marginal revenue $p$ to marginal cost $h + Hq$.\n",
+ "\n",
+ "This yields a competitive producer's inverse supply curve.\n",
+ "\n",
+ "A monopolist's marginal revenue is not constant but instead is a non-trivial function of the quantity it sets.\n",
+ "\n",
+ "The monopolist's marginal revenue is\n",
+ "\n",
+ "$$\n",
+ "MR(q) = -2\\mu^{-1}\\Pi^{\\top}\\Pi q+\\mu^{-1}\\Pi^{\\top}b,\n",
+ "$$\n",
+ "\n",
+ "which the monopolist equates to its marginal cost.\n",
+ "\n",
+ "The plot indicates that the monopolist's sets output lower than either the competitive equilibrium quantity.\n",
+ "\n",
+ "In a single good case, this equilibrium is associated with a higher price of the good."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c2df090e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "class Monopoly(ProductionEconomy):\n",
+ " \n",
+ " def __init__(self, \n",
+ " Π, \n",
+ " b, \n",
+ " h, \n",
+ " J, \n",
+ " μ):\n",
+ " \"\"\"\n",
+ " Inherit all properties and methods from class ProductionEconomy\n",
+ " \"\"\"\n",
+ " super().__init__(Π, b, h, J, μ)\n",
+ " \n",
+ "\n",
+ " def equilibrium_with_monopoly(self):\n",
+ " \"\"\"\n",
+ " Compute the equilibrium price and allocation when there is a monopolist supplier\n",
+ " \"\"\"\n",
+ " Π, b, h, μ, J = self.Π, self.b, self.h, self.μ, self.J\n",
+ " H = .5 * (J + J.T)\n",
+ "\n",
+ " # allocation\n",
+ " q = inv(μ * H + 2 * Π.T @ Π) @ (Π.T @ b - μ * h)\n",
+ "\n",
+ " # price\n",
+ " p = 1 / μ * (Π.T @ b - Π.T @ Π @ q)\n",
+ "\n",
+ " if any(Π @ q - b >= 0):\n",
+ " raise Exception('invalid result: set bliss points further away')\n",
+ "\n",
+ " return q, p"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0bbab98d",
+ "metadata": {},
+ "source": [
+ "Define a function that plots the demand, marginal cost and marginal revenue curves with surpluses and equilibrium labelled."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c8ce68e3",
+ "metadata": {
+ "tags": [
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "def plot_monopoly(M):\n",
+ " \"\"\"\n",
+ " Plot demand curve, marginal production cost and revenue, surpluses and the\n",
+ " equilibrium in a monopolist supplier economy with a single good\n",
+ "\n",
+ " Args:\n",
+ " M (class): A class inherits class ProductionEconomy with monopoly\n",
+ " \"\"\"\n",
+ " # get singleton value\n",
+ " J, h, Π, b, μ = M.J.item(), M.h.item(), M.Π.item(), M.b.item(), M.μ\n",
+ " H = J\n",
+ "\n",
+ " # compute competitive equilibrium\n",
+ " c, p = M.competitive_equilibrium()\n",
+ " q, pm = M.equilibrium_with_monopoly()\n",
+ " c, p, q, pm = c.item(), p.item(), q.item(), pm.item()\n",
+ "\n",
+ " # compute\n",
+ "\n",
+ " # inverse supply/demand curve\n",
+ " marg_cost = lambda x: h + H * x\n",
+ " marg_rev = lambda x: -2 * 1 / μ * Π * Π * x + 1 / μ * Π * b\n",
+ " demand_inv = lambda x: 1 / μ * (Π * b - Π * Π * x)\n",
+ "\n",
+ " xs = np.linspace(0, 2 * c, 100)\n",
+ " pms = np.ones(100) * pm\n",
+ " marg_cost_curve = marg_cost(xs)\n",
+ " marg_rev_curve = marg_rev(xs)\n",
+ " demand_curve = demand_inv(xs)\n",
+ "\n",
+ " # plot\n",
+ " plt.figure()\n",
+ " plt.plot(xs, marg_cost_curve, label='Marginal cost', color='#020060')\n",
+ " plt.plot(xs, marg_rev_curve, label='Marginal revenue', color='#E55B13')\n",
+ " plt.plot(xs, demand_curve, label='Demand', color='#600001')\n",
+ "\n",
+ " plt.fill_between(xs[xs <= q], demand_curve[xs <= q], pms[xs <= q], label='Consumer surplus', color='#EED1CF')\n",
+ " plt.fill_between(xs[xs <= q], marg_cost_curve[xs <= q], pms[xs <= q], label='Producer surplus', color='#E6E6F5')\n",
+ "\n",
+ " plt.vlines(c, 0, p, linestyle=\"dashed\", color='black', alpha=0.7)\n",
+ " plt.hlines(p, 0, c, linestyle=\"dashed\", color='black', alpha=0.7)\n",
+ " plt.scatter(c, p, zorder=10, label='Competitive equilibrium', color='#600001')\n",
+ "\n",
+ " plt.vlines(q, 0, pm, linestyle=\"dashed\", color='black', alpha=0.7)\n",
+ " plt.hlines(pm, 0, q, linestyle=\"dashed\", color='black', alpha=0.7)\n",
+ " plt.scatter(q, pm, zorder=10, label='Equilibrium with monopoly', color='#E55B13')\n",
+ "\n",
+ " plt.legend(loc='upper right')\n",
+ " plt.margins(x=0, y=0)\n",
+ " plt.ylim(0)\n",
+ " plt.xlabel('Quantity')\n",
+ " plt.ylabel('Price')\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "dd3f2961",
+ "metadata": {},
+ "source": [
+ "#### A multiple good example\n",
+ "\n",
+ "Let's compare competitive equilibrium and monopoly outcomes in a multiple goods economy."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "71a2d05a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Π = np.array([[1, 0],\n",
+ " [0, 1.2]])\n",
+ "\n",
+ "b = np.array([10, 10])\n",
+ "\n",
+ "h = np.array([0.5, 0.5])\n",
+ "\n",
+ "J = np.array([[1, 0.5],\n",
+ " [0.5, 1]])\n",
+ "μ = 1\n",
+ "\n",
+ "M = Monopoly(Π, b, h, J, μ)\n",
+ "c, p = M.competitive_equilibrium()\n",
+ "q, pm = M.equilibrium_with_monopoly()\n",
+ "\n",
+ "print('Competitive equilibrium price:', p)\n",
+ "print('Competitive equilibrium allocation:', c)\n",
+ "\n",
+ "print('Equilibrium with monopolist supplier price:', pm)\n",
+ "print('Equilibrium with monopolist supplier allocation:', q)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0c0d5c16",
+ "metadata": {},
+ "source": [
+ "#### A single-good example"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "0ff3767b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Π = np.array([[1]]) # the matrix now is a singleton\n",
+ "b = np.array([10])\n",
+ "h = np.array([0.5])\n",
+ "J = np.array([[1]])\n",
+ "μ = 1\n",
+ "\n",
+ "M = Monopoly(Π, b, h, J, μ)\n",
+ "c, p = M.competitive_equilibrium()\n",
+ "q, pm = M.equilibrium_with_monopoly()\n",
+ "\n",
+ "print('Competitive equilibrium price:', p.item())\n",
+ "print('Competitive equilibrium allocation:', c.item())\n",
+ "\n",
+ "print('Equilibrium with monopolist supplier price:', pm.item())\n",
+ "print('Equilibrium with monopolist supplier allocation:', q.item())\n",
+ "\n",
+ "# plot\n",
+ "plot_monopoly(M)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8424a928",
+ "metadata": {},
+ "source": [
+ "## Multi-good welfare maximization problem\n",
+ "\n",
+ "Our welfare maximization problem -- also sometimes called a social planning problem -- is to choose $c$ to maximize\n",
+ "\n",
+ "$$\n",
+ " - \\frac{1}{2} \\mu^{-1}(\\Pi c -b) ^\\top (\\Pi c -b )\n",
+ "$$\n",
+ "\n",
+ "minus the area under the inverse supply curve, namely,\n",
+ "\n",
+ "$$\n",
+ " h c + \\frac{1}{2} c^\\top J c \n",
+ "$$\n",
+ "\n",
+ "So the welfare criterion is\n",
+ "\n",
+ "$$\n",
+ " - \\frac{1}{2} \\mu^{-1}(\\Pi c -b)^\\top (\\Pi c -b ) -h c \n",
+ " - \\frac{1}{2} c^\\top J c\n",
+ "$$\n",
+ "\n",
+ "In this formulation, $\\mu$ is a parameter that describes how the planner weighs interests of outside suppliers and our representative consumer.\n",
+ "\n",
+ "The first-order condition with respect to $c$ is\n",
+ "\n",
+ "$$\n",
+ "- \\mu^{-1} \\Pi^\\top \\Pi c + \\mu^{-1}\\Pi^\\top b - h - H c = 0\n",
+ "$$\n",
+ "\n",
+ "which implies {eq}`eq:old5p`.\n",
+ "\n",
+ "Thus, as for the single-good case, with multiple goods a competitive equilibrium quantity vector solves a planning problem.\n",
+ "\n",
+ "(This is another version of the first welfare theorem.)\n",
+ "\n",
+ "We can deduce a competitive equilibrium price vector from either\n",
+ "\n",
+ " * the inverse demand curve, or\n",
+ "\n",
+ " * the inverse supply curve"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.14.5"
+ }
+ },
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "source_map": [
+ 12,
+ 58,
+ 63,
+ 95,
+ 102,
+ 138,
+ 226,
+ 271,
+ 306,
+ 367,
+ 382,
+ 420,
+ 446,
+ 450,
+ 454,
+ 469,
+ 486,
+ 496,
+ 503,
+ 507,
+ 513,
+ 517,
+ 532,
+ 537,
+ 638,
+ 654,
+ 716,
+ 720,
+ 766,
+ 782,
+ 799,
+ 804,
+ 808,
+ 819,
+ 824,
+ 828,
+ 838,
+ 849,
+ 868,
+ 877,
+ 889,
+ 895,
+ 938,
+ 971,
+ 1003,
+ 1007,
+ 1063,
+ 1069,
+ 1090,
+ 1094,
+ 1113
+ ]
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/supply_demand_multiple_goods.md b/book/_build/html/_sources/supply_demand_multiple_goods.md
new file mode 100644
index 0000000..5a010ce
--- /dev/null
+++ b/book/_build/html/_sources/supply_demand_multiple_goods.md
@@ -0,0 +1,1154 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.14.5
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+(supply_demand_multiple_goods)=
+# Supply and Demand with Many Goods
+
+## Overview
+
+In a {doc}`previous lecture ` we studied supply, demand
+and welfare in a market with a single consumption good.
+
+In this lecture, we study a setting with $n$ goods and $n$ corresponding prices.
+
+Key infrastructure concepts that we'll encounter in this lecture are
+
+* inverse demand curves
+* marginal utilities of wealth
+* inverse supply curves
+* consumer surplus
+* producer surplus
+* social welfare as a sum of consumer and producer surpluses
+* competitive equilibrium
+
+
+We will provide a version of the [first fundamental welfare theorem](https://en.wikipedia.org/wiki/Fundamental_theorems_of_welfare_economics), which was formulated by
+
+* [Leon Walras](https://en.wikipedia.org/wiki/L%C3%A9on_Walras)
+* [Francis Ysidro Edgeworth](https://en.wikipedia.org/wiki/Francis_Ysidro_Edgeworth)
+* [Vilfredo Pareto](https://en.wikipedia.org/wiki/Vilfredo_Pareto)
+
+Important extensions to the key ideas were obtained by
+
+* [Abba Lerner](https://en.wikipedia.org/wiki/Abba_P._Lerner)
+* [Harold Hotelling](https://en.wikipedia.org/wiki/Harold_Hotelling)
+* [Paul Samuelson](https://en.wikipedia.org/wiki/Paul_Samuelson)
+* [Kenneth Arrow](https://en.wikipedia.org/wiki/Kenneth_Arrow)
+* [Gerard Debreu](https://en.wikipedia.org/wiki/G%C3%A9rard_Debreu)
+
+
+We shall describe two classic welfare theorems:
+
+* **first welfare theorem:** for a given distribution of wealth among consumers, a competitive equilibrium allocation of goods solves a social planning problem.
+
+* **second welfare theorem:** An allocation of goods to consumers that solves a social planning problem can be supported by a competitive equilibrium with an appropriate initial distribution of wealth.
+
+As usual, we start by importing some Python modules.
+
+```{code-cell} ipython3
+# import some packages
+import numpy as np
+import matplotlib.pyplot as plt
+from scipy.linalg import inv
+```
+
+## Formulas from linear algebra
+
+We shall apply formulas from linear algebra that
+
+* differentiate an inner product with respect to each vector
+* differentiate a product of a matrix and a vector with respect to the vector
+* differentiate a quadratic form in a vector with respect to the vector
+
+Where $a$ is an $n \times 1$ vector, $A$ is an $n \times n$ matrix, and $x$ is an $n \times 1$ vector:
+
+$$
+\frac{\partial a^\top x }{\partial x} = \frac{\partial x^\top a }{\partial x} = a
+$$
+
+$$
+\frac{\partial A x} {\partial x} = A
+$$
+
+$$
+\frac{\partial x^\top A x}{\partial x} = (A + A^\top)x
+$$
+
+## From utility function to demand curve
+
+Our study of consumers will use the following primitives
+
+* $\Pi$ be an $m \times n$ matrix,
+* $b$ be an $m \times 1$ vector of bliss points,
+* $e$ be an $n \times 1$ vector of endowments, and
+
++++
+
+We will analyze endogenous objects $c$ and $p$, where
+
+* $c$ is an $n \times 1$ vector of consumptions of various goods,
+* $p$ is an $n \times 1$ vector of prices
+
++++
+
+The matrix $\Pi$ describes a consumer's willingness to substitute one good for every other good.
+
+We assume that $\Pi$ has linearly independent columns, which implies that $\Pi^\top \Pi$ is a positive definite matrix.
+
+* it follows that $\Pi^\top \Pi$ has an inverse.
+
+We shall see below that $(\Pi^\top \Pi)^{-1}$ is a matrix of slopes of (compensated) demand curves for $c$ with respect to a vector of prices:
+
+$$
+ \frac{\partial c } {\partial p} = (\Pi^\top \Pi)^{-1}
+$$
+
+A consumer faces $p$ as a price taker and chooses $c$ to maximize the utility function
+
+$$
+ - \frac{1}{2} (\Pi c -b) ^\top (\Pi c -b )
+$$ (eq:old0)
+
+subject to the budget constraint
+
+$$
+ p^\top (c -e ) = 0
+$$ (eq:old2)
+
+We shall specify examples in which $\Pi$ and $b$ are such that it typically happens that
+
+$$
+ \Pi c \ll b
+$$ (eq:bversusc)
+
+This means that the consumer has much less of each good than he wants.
+
+The deviation in {eq}`eq:bversusc` will ultimately assure us that competitive equilibrium prices are positive.
+
++++
+
+### Demand curve implied by constrained utility maximization
+
+For now, we assume that the budget constraint is {eq}`eq:old2`.
+
+So we'll be deriving what is known as a **Marshallian** demand curve.
+
+Our aim is to maximize [](eq:old0) subject to [](eq:old2).
+
+Form a Lagrangian
+
+$$ L = - \frac{1}{2} (\Pi c -b)^\top (\Pi c -b ) + \mu [p^\top (e-c)] $$
+
+where $\mu$ is a Lagrange multiplier that is often called a **marginal utility of wealth**.
+
+The consumer chooses $c$ to maximize $L$ and $\mu$ to minimize it.
+
+First-order conditions for $c$ are
+
+$$
+ \frac{\partial L} {\partial c}
+ = - \Pi^\top \Pi c + \Pi^\top b - \mu p = 0
+$$
+
+so that, given $\mu$, the consumer chooses
+
+$$
+ c = (\Pi^\top \Pi )^{-1}(\Pi^\top b - \mu p )
+$$ (eq:old3)
+
+Substituting {eq}`eq:old3` into budget constraint {eq}`eq:old2` and solving for $\mu$ gives
+
+$$
+ \mu(p,e) = \frac{p^\top ( \Pi^\top \Pi )^{-1} \Pi^\top b - p^\top e}{p^\top (\Pi^\top \Pi )^{-1} p}.
+$$ (eq:old4)
+
+Equation {eq}`eq:old4` tells how marginal utility of wealth depends on the endowment vector $e$ and the price vector $p$.
+
+```{note}
+Equation {eq}`eq:old4` is a consequence of imposing that $p^\top (c - e) = 0$.
+
+We could instead take $\mu$ as a parameter and use {eq}`eq:old3` and the budget constraint {eq}`eq:old2p` to solve for wealth.
+
+Which way we proceed determines whether we are constructing a **Marshallian** or **Hicksian** demand curve.
+```
+
+## Endowment economy
+
+We now study a pure-exchange economy, or what is sometimes called an endowment economy.
+
+Consider a single-consumer, multiple-goods economy without production.
+
+The only source of goods is the single consumer's endowment vector $e$.
+
+A competitive equilibrium price vector induces the consumer to choose $c=e$.
+
+This implies that the equilibrium price vector satisfies
+
+$$
+p = \mu^{-1} (\Pi^\top b - \Pi^\top \Pi e)
+$$
+
+In the present case where we have imposed budget constraint in the form {eq}`eq:old2`, we are free to normalize the price vector by setting the marginal utility of wealth $\mu =1$ (or any other value for that matter).
+
+This amounts to choosing a common unit (or numeraire) in which prices of all goods are expressed.
+
+(Doubling all prices will affect neither quantities nor relative prices.)
+
+We'll set $\mu=1$.
+
+```{exercise}
+:label: sdm_ex1
+
+Verify that setting $\mu=1$ in {eq}`eq:old3` implies that formula {eq}`eq:old4` is satisfied.
+
+```
+
+```{exercise}
+:label: sdm_ex2
+
+Verify that setting $\mu=2$ in {eq}`eq:old3` also implies that formula
+{eq}`eq:old4` is satisfied.
+
+```
+
+Here is a class that computes competitive equilibria for our economy.
+
+```{code-cell} ipython3
+class ExchangeEconomy:
+
+ def __init__(self,
+ Π,
+ b,
+ e,
+ thres=1.5):
+ """
+ Set up the environment for an exchange economy
+
+ Args:
+ Π (np.array): shared matrix of substitution
+ b (list): the consumer's bliss point
+ e (list): the consumer's endowment
+ thres (float): a threshold to check p >> Π e condition
+ """
+
+ # check non-satiation
+ if np.min(b / np.max(Π @ e)) <= thres:
+ raise Exception('set bliss points further away')
+
+
+ self.Π, self.b, self.e = Π, b, e
+
+
+ def competitive_equilibrium(self):
+ """
+ Compute the competitive equilibrium prices and allocation
+ """
+ Π, b, e = self.Π, self.b, self.e
+
+ # compute price vector with μ=1
+ p = Π.T @ b - Π.T @ Π @ e
+
+ # compute consumption vector
+ slope_dc = inv(Π.T @ Π)
+ Π_inv = inv(Π)
+ c = Π_inv @ b - slope_dc @ p
+
+ if any(c < 0):
+ print('allocation: ', c)
+ raise Exception('negative allocation: equilibrium does not exist')
+
+ return p, c
+```
+
+## Digression: Marshallian and Hicksian demand curves
+
+Sometimes we'll use budget constraint {eq}`eq:old2` in situations in which a consumer's endowment vector $e$ is his **only** source of income.
+
+Other times we'll instead assume that the consumer has another source of income (positive or negative) and write his budget constraint as
+
+$$
+p ^\top (c -e ) = w
+$$ (eq:old2p)
+
+where $w$ is measured in "dollars" (or some other **numeraire**) and component $p_i$ of the price vector is measured in dollars per unit of good $i$.
+
+Whether the consumer's budget constraint is {eq}`eq:old2` or {eq}`eq:old2p` and whether we take $w$ as a free parameter or instead as an endogenous variable will affect the consumer's marginal utility of wealth.
+
+Consequently, how we set $\mu$ determines whether we are constructing
+
+* a **Marshallian** demand curve, as when we use {eq}`eq:old2` and solve for $\mu$ using equation {eq}`eq:old4` above, or
+* a **Hicksian** demand curve, as when we treat $\mu$ as a fixed parameter and solve for $w$ from {eq}`eq:old2p`.
+
+Marshallian and Hicksian demand curves contemplate different mental experiments:
+
+For a Marshallian demand curve, hypothetical changes in a price vector have both **substitution** and **income** effects
+
+* income effects are consequences of changes in $p^\top e$ associated with the change in the price vector
+
+For a Hicksian demand curve, hypothetical price vector changes have only **substitution** effects
+
+* changes in the price vector leave the $p^\top e + w$ unaltered because we freeze $\mu$ and solve for $w$
+
+Sometimes a Hicksian demand curve is called a **compensated** demand curve in order to emphasize that, to disarm the income (or wealth) effect associated with a price change, the consumer's wealth $w$ is adjusted.
+
+We'll discuss these distinct demand curves more below.
+
++++
+
+## Dynamics and risk as special cases
+
+Special cases of our $n$-good pure exchange model can be created to represent
+
+* **dynamics** --- by putting different dates on different commodities
+* **risk** --- by interpreting delivery of goods as being contingent on states of the world whose realizations are described by a *known probability distribution*
+
+Let's illustrate how.
+
+### Dynamics
+
+Suppose that we want to represent a utility function
+
+$$
+ - \frac{1}{2} [(c_1 - b_1)^2 + \beta (c_2 - b_2)^2]
+$$
+
+where $\beta \in (0,1)$ is a discount factor, $c_1$ is consumption at time $1$ and $c_2$ is consumption at time 2.
+
+To capture this with our quadratic utility function {eq}`eq:old0`, set
+
+$$
+\Pi = \begin{bmatrix} 1 & 0 \cr
+ 0 & \sqrt{\beta} \end{bmatrix}
+$$
+
+$$
+e = \begin{bmatrix} e_1 \cr e_2 \end{bmatrix}
+$$
+
+and
+
+$$
+b = \begin{bmatrix} b_1 \cr \sqrt{\beta} b_2
+\end{bmatrix}
+$$
+
+The budget constraint {eq}`eq:old2` becomes
+
+$$
+p_1 c_1 + p_2 c_2 = p_1 e_1 + p_2 e_2
+$$
+
+The left side is the **discounted present value** of consumption.
+
+The right side is the **discounted present value** of the consumer's endowment.
+
+The relative price $\frac{p_1}{p_2}$ has units of time $2$ goods per unit of time $1$ goods.
+
+Consequently,
+
+$$
+ (1+r) := R := \frac{p_1}{p_2}
+$$
+
+is the **gross interest rate** and $r$ is the **net interest rate**.
+
+Here is an example.
+
+```{code-cell} ipython3
+beta = 0.95
+
+Π = np.array([[1, 0],
+ [0, np.sqrt(beta)]])
+
+b = np.array([5, np.sqrt(beta) * 5])
+
+e = np.array([1, 1])
+
+dynamics = ExchangeEconomy(Π, b, e)
+p, c = dynamics.competitive_equilibrium()
+
+print('Competitive equilibrium price vector:', p)
+print('Competitive equilibrium allocation:', c)
+```
+
+### Risk and state-contingent claims
+
+We study risk in the context of a **static** environment, meaning that there is only one period.
+
+By **risk** we mean that an outcome is not known in advance, but that it is governed by a known probability distribution.
+
+As an example, our consumer confronts **risk** means in particular that
+
+ * there are two states of nature, $1$ and $2$.
+
+ * the consumer knows that the probability that state $1$ occurs is $\lambda$.
+
+ * the consumer knows that the probability that state $2$ occurs is $(1-\lambda)$.
+
+Before the outcome is realized, the consumer's **expected utility** is
+
+$$
+- \frac{1}{2} [\lambda (c_1 - b_1)^2 + (1-\lambda)(c_2 - b_2)^2]
+$$
+
+where
+
+* $c_1$ is consumption in state $1$
+* $c_2$ is consumption in state $2$
+
+To capture these preferences we set
+
+$$
+\Pi = \begin{bmatrix} \sqrt{\lambda} & 0 \cr
+ 0 & \sqrt{1-\lambda} \end{bmatrix}
+$$
+
+$$
+e = \begin{bmatrix} e_1 \cr e_2 \end{bmatrix}
+$$
+
++++
+
+$$
+b = \begin{bmatrix} \sqrt{\lambda}b_1 \cr \sqrt{1-\lambda}b_2 \end{bmatrix}
+$$
+
+A consumer's endowment vector is
+
+$$
+c = \begin{bmatrix} c_1 \cr c_2 \end{bmatrix}
+$$
+
+A price vector is
+
+$$
+p = \begin{bmatrix} p_1 \cr p_2 \end{bmatrix}
+$$
+
+where $p_i$ is the price of one unit of consumption in state $i \in \{1, 2\}$.
+
+The state-contingent goods being traded are often called **Arrow securities**.
+
+Before the random state of the world $i$ is realized, the consumer sells his/her state-contingent endowment bundle and purchases a state-contingent consumption bundle.
+
+Trading such state-contingent goods is one way economists often model **insurance**.
+
++++
+
+We use the tricks described above to interpret $c_1, c_2$ as "Arrow securities" that are state-contingent claims to consumption goods.
+
++++
+
+Here is an instance of the risk economy:
+
+```{code-cell} ipython3
+prob = 0.2
+
+Π = np.array([[np.sqrt(prob), 0],
+ [0, np.sqrt(1 - prob)]])
+
+b = np.array([np.sqrt(prob) * 5, np.sqrt(1 - prob) * 5])
+
+e = np.array([1, 1])
+
+risk = ExchangeEconomy(Π, b, e)
+p, c = risk.competitive_equilibrium()
+
+print('Competitive equilibrium price vector:', p)
+print('Competitive equilibrium allocation:', c)
+```
+
+```{exercise}
+:label: sdm_ex3
+
+Consider the instance above.
+
+Please numerically study how each of the following cases affects the equilibrium prices and allocations:
+
+* the consumer gets poorer,
+* they like the first good more, or
+* the probability that state $1$ occurs is higher.
+
+Hints. For each case choose some parameter $e, b, \text{ or } \lambda$ different from the instance.
+
+```
+
++++
+
+```{solution-start} sdm_ex3
+:class: dropdown
+```
+
+First consider when the consumer is poorer.
+
+Here we just decrease the endowment.
+
+```{code-cell} ipython3
+risk.e = np.array([0.5, 0.5])
+
+p, c = risk.competitive_equilibrium()
+
+print('Competitive equilibrium price vector:', p)
+print('Competitive equilibrium allocation:', c)
+```
+
+If the consumer likes the first (or second) good more, then we can set a larger bliss value for good 1.
+
+```{code-cell} ipython3
+risk.b = np.array([np.sqrt(prob) * 6, np.sqrt(1 - prob) * 5])
+p, c = risk.competitive_equilibrium()
+
+print('Competitive equilibrium price vector:', p)
+print('Competitive equilibrium allocation:', c)
+```
+
+Increase the probability that state $1$ occurs.
+
+```{code-cell} ipython3
+prob = 0.8
+
+Π = np.array([[np.sqrt(prob), 0],
+ [0, np.sqrt(1 - prob)]])
+
+b = np.array([np.sqrt(prob) * 5, np.sqrt(1 - prob) * 5])
+
+e = np.array([1, 1])
+
+risk = ExchangeEconomy(Π, b, e)
+p, c = risk.competitive_equilibrium()
+
+print('Competitive equilibrium price vector:', p)
+print('Competitive equilibrium allocation:', c)
+```
+
+```{solution-end}
+```
+
++++
+
+## Economies with endogenous supplies of goods
+
+Up to now we have described a pure exchange economy in which endowments of goods are exogenous, meaning that they are taken as given from outside the model.
+
+### Supply curve of a competitive firm
+
+A competitive firm that can produce goods takes a price vector $p$ as given and chooses a quantity $q$
+to maximize total revenue minus total costs.
+
+The firm's total revenue equals $p^\top q$ and its total cost equals $C(q)$ where $C(q)$ is a total cost function
+
+$$
+C(q) = h ^\top q + \frac{1}{2} q^\top J q
+$$
+
+
+and $J$ is a positive definite matrix.
+
+
+So the firm's profits are
+
+$$
+p^\top q - C(q)
+$$ (eq:compprofits)
+
+
+
+An $n\times 1$ vector of **marginal costs** is
+
+$$
+\frac{\partial C(q)}{\partial q} = h + H q
+$$
+
+where
+
+$$
+H = \frac{1}{2} (J + J^\top)
+$$
+
+The firm maximizes total profits by setting **marginal revenue to marginal costs**.
+
+An $n \times 1$ vector of marginal revenues for the price-taking firm is $\frac{\partial p^\top q}
+{\partial q} = p $.
+
+So **price equals marginal revenue** for our price-taking competitive firm.
+
+This leads to the following **inverse supply curve** for the competitive firm:
+
+
+$$
+p = h + H q
+$$
+
+
+
+
+### Competitive equilibrium
+
+
+To compute a competitive equilibrium for a production economy where demand curve is pinned down by the marginal utility of wealth $\mu$, we first compute an allocation by solving a planning problem.
+
+Then we compute the equilibrium price vector using the inverse demand or supply curve.
+
+#### $\mu=1$ warmup
+
+As a special case, let's pin down a demand curve by setting the marginal utility of wealth $\mu =1$.
+
+Equating supply price to demand price and letting $q=c$ we get
+
+$$
+p = h + H c = \Pi^\top b - \Pi^\top \Pi c ,
+$$
+
+which implies the equilibrium quantity vector
+
+$$
+c = (\Pi^\top \Pi + H )^{-1} ( \Pi^\top b - h)
+$$ (eq:old5)
+
+This equation is the counterpart of equilibrium quantity {eq}`eq:old1` for the scalar $n=1$ model with which we began.
+
+#### General $\mu\neq 1$ case
+
+Now let's extend the preceding analysis to a more
+general case by allowing $\mu \neq 1$.
+
+Then the inverse demand curve is
+
+$$
+p = \mu^{-1} [\Pi^\top b - \Pi^\top \Pi c]
+$$ (eq:old5pa)
+
+Equating this to the inverse supply curve, letting $q=c$ and solving
+for $c$ gives
+
+$$
+c = [\Pi^\top \Pi + \mu H]^{-1} [ \Pi^\top b - \mu h]
+$$ (eq:old5p)
+
++++
+
+### Implementation
+
+A Production Economy will consist of
+
+* a single **person** that we'll interpret as a representative consumer
+* a single set of **production costs**
+* a multiplier $\mu$ that weights "consumers" versus "producers" in a planner's welfare function, as described above in the main text
+* an $n \times 1$ vector $p$ of competitive equilibrium prices
+* an $n \times 1$ vector $c$ of competitive equilibrium quantities
+* **consumer surplus**
+* **producer surplus**
+
+Here we define a class ``ProductionEconomy``.
+
+```{code-cell} ipython3
+class ProductionEconomy:
+
+ def __init__(self,
+ Π,
+ b,
+ h,
+ J,
+ μ):
+ """
+ Set up the environment for a production economy
+
+ Args:
+ Π (np.ndarray): matrix of substitution
+ b (np.array): bliss points
+ h (np.array): h in cost func
+ J (np.ndarray): J in cost func
+ μ (float): welfare weight of the corresponding planning problem
+ """
+ self.n = len(b)
+ self.Π, self.b, self.h, self.J, self.μ = Π, b, h, J, μ
+
+ def competitive_equilibrium(self):
+ """
+ Compute a competitive equilibrium of the production economy
+ """
+ Π, b, h, μ, J = self.Π, self.b, self.h, self.μ, self.J
+ H = .5 * (J + J.T)
+
+ # allocation
+ c = inv(Π.T @ Π + μ * H) @ (Π.T @ b - μ * h)
+
+ # price
+ p = 1 / μ * (Π.T @ b - Π.T @ Π @ c)
+
+ # check non-satiation
+ if any(Π @ c - b >= 0):
+ raise Exception('invalid result: set bliss points further away')
+
+ return c, p
+
+ def compute_surplus(self):
+ """
+ Compute consumer and producer surplus for single good case
+ """
+ if self.n != 1:
+ raise Exception('not single good')
+ h, J, Π, b, μ = self.h.item(), self.J.item(), self.Π.item(), self.b.item(), self.μ
+ H = J
+
+ # supply/demand curve coefficients
+ s0, s1 = h, H
+ d0, d1 = 1 / μ * Π * b, 1 / μ * Π**2
+
+ # competitive equilibrium
+ c, p = self.competitive_equilibrium()
+
+ # calculate surplus
+ c_surplus = d0 * c - .5 * d1 * c**2 - p * c
+ p_surplus = p * c - s0 * c - .5 * s1 * c**2
+
+ return c_surplus, p_surplus
+```
+
+Then define a function that plots demand and supply curves and labels surpluses and equilibrium.
+
+```{code-cell} ipython3
+:tags: [hide-input]
+
+def plot_competitive_equilibrium(PE):
+ """
+ Plot demand and supply curves, producer/consumer surpluses, and equilibrium for
+ a single good production economy
+
+ Args:
+ PE (class): A initialized production economy class
+ """
+ # get singleton value
+ J, h, Π, b, μ = PE.J.item(), PE.h.item(), PE.Π.item(), PE.b.item(), PE.μ
+ H = J
+
+ # compute competitive equilibrium
+ c, p = PE.competitive_equilibrium()
+ c, p = c.item(), p.item()
+
+ # inverse supply/demand curve
+ supply_inv = lambda x: h + H * x
+ demand_inv = lambda x: 1 / μ * (Π * b - Π * Π * x)
+
+ xs = np.linspace(0, 2 * c, 100)
+ ps = np.ones(100) * p
+ supply_curve = supply_inv(xs)
+ demand_curve = demand_inv(xs)
+
+ # plot
+ plt.figure()
+ plt.plot(xs, supply_curve, label='Supply', color='#020060')
+ plt.plot(xs, demand_curve, label='Demand', color='#600001')
+
+ plt.fill_between(xs[xs <= c], demand_curve[xs <= c], ps[xs <= c], label='Consumer surplus', color='#EED1CF')
+ plt.fill_between(xs[xs <= c], supply_curve[xs <= c], ps[xs <= c], label='Producer surplus', color='#E6E6F5')
+
+ plt.vlines(c, 0, p, linestyle="dashed", color='black', alpha=0.7)
+ plt.hlines(p, 0, c, linestyle="dashed", color='black', alpha=0.7)
+ plt.scatter(c, p, zorder=10, label='Competitive equilibrium', color='#600001')
+
+ plt.legend(loc='upper right')
+ plt.margins(x=0, y=0)
+ plt.ylim(0)
+ plt.xlabel('Quantity')
+ plt.ylabel('Price')
+ plt.show()
+```
+
+#### Example: single agent with one good and production
+
+Now let's construct an example of a production economy with one good.
+
+To do this we
+
+ * specify a single **person** and a **cost curve** in a way that let's us replicate the simple single-good supply demand example with which we started
+
+ * compute equilibrium $p$ and $c$ and consumer and producer surpluses
+
+ * draw graphs of both surpluses
+
+ * do experiments in which we shift $b$ and watch what happens to $p, c$.
+
+```{code-cell} ipython3
+Π = np.array([[1]]) # the matrix now is a singleton
+b = np.array([10])
+h = np.array([0.5])
+J = np.array([[1]])
+μ = 1
+
+PE = ProductionEconomy(Π, b, h, J, μ)
+c, p = PE.competitive_equilibrium()
+
+print('Competitive equilibrium price:', p.item())
+print('Competitive equilibrium allocation:', c.item())
+
+# plot
+plot_competitive_equilibrium(PE)
+```
+
+```{code-cell} ipython3
+c_surplus, p_surplus = PE.compute_surplus()
+
+print('Consumer surplus:', c_surplus.item())
+print('Producer surplus:', p_surplus.item())
+```
+
+Let's give the consumer a lower welfare weight by raising $\mu$.
+
+```{code-cell} ipython3
+PE.μ = 2
+c, p = PE.competitive_equilibrium()
+
+print('Competitive equilibrium price:', p.item())
+print('Competitive equilibrium allocation:', c.item())
+
+# plot
+plot_competitive_equilibrium(PE)
+```
+
+```{code-cell} ipython3
+c_surplus, p_surplus = PE.compute_surplus()
+
+print('Consumer surplus:', c_surplus.item())
+print('Producer surplus:', p_surplus.item())
+```
+
+Now we change the bliss point so that the consumer derives more utility from consumption.
+
+```{code-cell} ipython3
+PE.μ = 1
+PE.b = PE.b * 1.5
+c, p = PE.competitive_equilibrium()
+
+print('Competitive equilibrium price:', p.item())
+print('Competitive equilibrium allocation:', c.item())
+
+# plot
+plot_competitive_equilibrium(PE)
+```
+
+This raises both the equilibrium price and quantity.
+
+
+#### Example: single agent two-good economy with production
+
+ * we'll do some experiments like those above
+
+ * we can do experiments with a **diagonal** $\Pi$ and also with a **non-diagonal** $\Pi$ matrices to study how cross-slopes affect responses of $p$ and $c$ to various shifts in $b$ (TODO)
+
+```{code-cell} ipython3
+Π = np.array([[1, 0],
+ [0, 1]])
+
+b = np.array([10, 10])
+
+h = np.array([0.5, 0.5])
+
+J = np.array([[1, 0.5],
+ [0.5, 1]])
+μ = 1
+
+PE = ProductionEconomy(Π, b, h, J, μ)
+c, p = PE.competitive_equilibrium()
+
+print('Competitive equilibrium price:', p)
+print('Competitive equilibrium allocation:', c)
+```
+
+```{code-cell} ipython3
+PE.b = np.array([12, 10])
+
+c, p = PE.competitive_equilibrium()
+
+print('Competitive equilibrium price:', p)
+print('Competitive equilibrium allocation:', c)
+```
+
+```{code-cell} ipython3
+PE.Π = np.array([[1, 0.5],
+ [0.5, 1]])
+
+PE.b = np.array([10, 10])
+
+c, p = PE.competitive_equilibrium()
+
+print('Competitive equilibrium price:', p)
+print('Competitive equilibrium allocation:', c)
+```
+
+```{code-cell} ipython3
+PE.b = np.array([12, 10])
+c, p = PE.competitive_equilibrium()
+
+print('Competitive equilibrium price:', p)
+print('Competitive equilibrium allocation:', c)
+```
+
+### Digression: a supplier who is a monopolist
+
+A competitive firm is a **price-taker** who regards the price and therefore its marginal revenue as being beyond its control.
+
+A monopolist knows that it has no competition and can influence the price and its marginal revenue by
+setting quantity.
+
+A monopolist takes a **demand curve** and not the **price** as beyond its control.
+
+Thus, instead of being a price-taker, a monopolist sets prices to maximize profits subject to the inverse demand curve
+{eq}`eq:old5pa`.
+
+So the monopolist's total profits as a function of its output $q$ is
+
+$$
+[\mu^{-1} \Pi^\top (b - \Pi q)]^\top q - h^\top q - \frac{1}{2} q^\top J q
+$$ (eq:monopprof)
+
+After finding
+first-order necessary conditions for maximizing monopoly profits with respect to $q$
+and solving them for $q$, we find that the monopolist sets
+
+$$
+q = (H + 2 \mu^{-1} \Pi^\top \Pi)^{-1} (\mu^{-1} \Pi^\top b - h)
+$$ (eq:qmonop)
+
+We'll soon see that a monopolist sets a **lower output** $q$ than does either a
+
+ * planner who chooses $q$ to maximize social welfare
+
+ * a competitive equilibrium
+
+
+
+```{exercise}
+:label: sdm_ex4
+
+Please verify the monopolist's supply curve {eq}`eq:qmonop`.
+
+```
+
++++
+
+### A monopolist
+
+Let's consider a monopolist supplier.
+
+We have included a method in our `ProductionEconomy` class to compute an equilibrium price and allocation when the supplier is a monopolist.
+
+Since the supplier now has the price-setting power
+
+- we first compute the optimal quantity that solves the monopolist's profit maximization problem.
+- Then we back out an equilibrium price from the consumer's inverse demand curve.
+
+Next, we use a graph for the single good case to illustrate the difference between a competitive equilibrium and an equilibrium with a monopolist supplier.
+
+Recall that in a competitive equilibrium, a price-taking supplier equates marginal revenue $p$ to marginal cost $h + Hq$.
+
+This yields a competitive producer's inverse supply curve.
+
+A monopolist's marginal revenue is not constant but instead is a non-trivial function of the quantity it sets.
+
+The monopolist's marginal revenue is
+
+$$
+MR(q) = -2\mu^{-1}\Pi^{\top}\Pi q+\mu^{-1}\Pi^{\top}b,
+$$
+
+which the monopolist equates to its marginal cost.
+
+The plot indicates that the monopolist's sets output lower than either the competitive equilibrium quantity.
+
+In a single good case, this equilibrium is associated with a higher price of the good.
+
+```{code-cell} ipython3
+class Monopoly(ProductionEconomy):
+
+ def __init__(self,
+ Π,
+ b,
+ h,
+ J,
+ μ):
+ """
+ Inherit all properties and methods from class ProductionEconomy
+ """
+ super().__init__(Π, b, h, J, μ)
+
+
+ def equilibrium_with_monopoly(self):
+ """
+ Compute the equilibrium price and allocation when there is a monopolist supplier
+ """
+ Π, b, h, μ, J = self.Π, self.b, self.h, self.μ, self.J
+ H = .5 * (J + J.T)
+
+ # allocation
+ q = inv(μ * H + 2 * Π.T @ Π) @ (Π.T @ b - μ * h)
+
+ # price
+ p = 1 / μ * (Π.T @ b - Π.T @ Π @ q)
+
+ if any(Π @ q - b >= 0):
+ raise Exception('invalid result: set bliss points further away')
+
+ return q, p
+```
+
+Define a function that plots the demand, marginal cost and marginal revenue curves with surpluses and equilibrium labelled.
+
+```{code-cell} ipython3
+:tags: [hide-input]
+
+def plot_monopoly(M):
+ """
+ Plot demand curve, marginal production cost and revenue, surpluses and the
+ equilibrium in a monopolist supplier economy with a single good
+
+ Args:
+ M (class): A class inherits class ProductionEconomy with monopoly
+ """
+ # get singleton value
+ J, h, Π, b, μ = M.J.item(), M.h.item(), M.Π.item(), M.b.item(), M.μ
+ H = J
+
+ # compute competitive equilibrium
+ c, p = M.competitive_equilibrium()
+ q, pm = M.equilibrium_with_monopoly()
+ c, p, q, pm = c.item(), p.item(), q.item(), pm.item()
+
+ # compute
+
+ # inverse supply/demand curve
+ marg_cost = lambda x: h + H * x
+ marg_rev = lambda x: -2 * 1 / μ * Π * Π * x + 1 / μ * Π * b
+ demand_inv = lambda x: 1 / μ * (Π * b - Π * Π * x)
+
+ xs = np.linspace(0, 2 * c, 100)
+ pms = np.ones(100) * pm
+ marg_cost_curve = marg_cost(xs)
+ marg_rev_curve = marg_rev(xs)
+ demand_curve = demand_inv(xs)
+
+ # plot
+ plt.figure()
+ plt.plot(xs, marg_cost_curve, label='Marginal cost', color='#020060')
+ plt.plot(xs, marg_rev_curve, label='Marginal revenue', color='#E55B13')
+ plt.plot(xs, demand_curve, label='Demand', color='#600001')
+
+ plt.fill_between(xs[xs <= q], demand_curve[xs <= q], pms[xs <= q], label='Consumer surplus', color='#EED1CF')
+ plt.fill_between(xs[xs <= q], marg_cost_curve[xs <= q], pms[xs <= q], label='Producer surplus', color='#E6E6F5')
+
+ plt.vlines(c, 0, p, linestyle="dashed", color='black', alpha=0.7)
+ plt.hlines(p, 0, c, linestyle="dashed", color='black', alpha=0.7)
+ plt.scatter(c, p, zorder=10, label='Competitive equilibrium', color='#600001')
+
+ plt.vlines(q, 0, pm, linestyle="dashed", color='black', alpha=0.7)
+ plt.hlines(pm, 0, q, linestyle="dashed", color='black', alpha=0.7)
+ plt.scatter(q, pm, zorder=10, label='Equilibrium with monopoly', color='#E55B13')
+
+ plt.legend(loc='upper right')
+ plt.margins(x=0, y=0)
+ plt.ylim(0)
+ plt.xlabel('Quantity')
+ plt.ylabel('Price')
+ plt.show()
+```
+
+#### A multiple good example
+
+Let's compare competitive equilibrium and monopoly outcomes in a multiple goods economy.
+
+```{code-cell} ipython3
+Π = np.array([[1, 0],
+ [0, 1.2]])
+
+b = np.array([10, 10])
+
+h = np.array([0.5, 0.5])
+
+J = np.array([[1, 0.5],
+ [0.5, 1]])
+μ = 1
+
+M = Monopoly(Π, b, h, J, μ)
+c, p = M.competitive_equilibrium()
+q, pm = M.equilibrium_with_monopoly()
+
+print('Competitive equilibrium price:', p)
+print('Competitive equilibrium allocation:', c)
+
+print('Equilibrium with monopolist supplier price:', pm)
+print('Equilibrium with monopolist supplier allocation:', q)
+```
+
+#### A single-good example
+
+```{code-cell} ipython3
+Π = np.array([[1]]) # the matrix now is a singleton
+b = np.array([10])
+h = np.array([0.5])
+J = np.array([[1]])
+μ = 1
+
+M = Monopoly(Π, b, h, J, μ)
+c, p = M.competitive_equilibrium()
+q, pm = M.equilibrium_with_monopoly()
+
+print('Competitive equilibrium price:', p.item())
+print('Competitive equilibrium allocation:', c.item())
+
+print('Equilibrium with monopolist supplier price:', pm.item())
+print('Equilibrium with monopolist supplier allocation:', q.item())
+
+# plot
+plot_monopoly(M)
+```
+
+## Multi-good welfare maximization problem
+
+Our welfare maximization problem -- also sometimes called a social planning problem -- is to choose $c$ to maximize
+
+$$
+ - \frac{1}{2} \mu^{-1}(\Pi c -b) ^\top (\Pi c -b )
+$$
+
+minus the area under the inverse supply curve, namely,
+
+$$
+ h c + \frac{1}{2} c^\top J c
+$$
+
+So the welfare criterion is
+
+$$
+ - \frac{1}{2} \mu^{-1}(\Pi c -b)^\top (\Pi c -b ) -h c
+ - \frac{1}{2} c^\top J c
+$$
+
+In this formulation, $\mu$ is a parameter that describes how the planner weighs interests of outside suppliers and our representative consumer.
+
+The first-order condition with respect to $c$ is
+
+$$
+- \mu^{-1} \Pi^\top \Pi c + \mu^{-1}\Pi^\top b - h - H c = 0
+$$
+
+which implies {eq}`eq:old5p`.
+
+Thus, as for the single-good case, with multiple goods a competitive equilibrium quantity vector solves a planning problem.
+
+(This is another version of the first welfare theorem.)
+
+We can deduce a competitive equilibrium price vector from either
+
+ * the inverse demand curve, or
+
+ * the inverse supply curve
diff --git a/book/_build/html/_sources/time_series_with_matrices.ipynb b/book/_build/html/_sources/time_series_with_matrices.ipynb
new file mode 100644
index 0000000..68744a7
--- /dev/null
+++ b/book/_build/html/_sources/time_series_with_matrices.ipynb
@@ -0,0 +1,1057 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "b878bee3",
+ "metadata": {},
+ "source": [
+ "(time_series_with_matrices)=\n",
+ "```{raw} jupyter\n",
+ "\n",
+ "```\n",
+ "\n",
+ "# Univariate Time Series with Matrix Algebra\n",
+ "\n",
+ "## Overview\n",
+ "\n",
+ "This lecture uses matrices to solve some linear difference equations.\n",
+ "\n",
+ "As a running example, we’ll study a **second-order linear difference\n",
+ "equation** that was the key technical tool in Paul Samuelson’s 1939\n",
+ "article {cite}`Samuelson1939` that introduced the *multiplier-accelerator model*.\n",
+ "\n",
+ "This model became the workhorse that powered early econometric versions of\n",
+ "Keynesian macroeconomic models in the United States.\n",
+ "\n",
+ "You can read about the details of that model in {doc}`intermediate:samuelson`.\n",
+ "\n",
+ "(That lecture also describes some technicalities about second-order linear difference equations.)\n",
+ "\n",
+ "In this lecture, we'll also learn about an **autoregressive** representation and a **moving average** representation of a non-stationary\n",
+ "univariate time series $\\{y_t\\}_{t=0}^T$.\n",
+ "\n",
+ "We'll also study a \"perfect foresight\" model of stock prices that involves solving\n",
+ "a \"forward-looking\" linear difference equation.\n",
+ "\n",
+ "We will use the following imports:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f1c8b44e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "from matplotlib import cm\n",
+ "\n",
+ "# Custom figsize for this lecture\n",
+ "plt.rcParams[\"figure.figsize\"] = (11, 5)\n",
+ "\n",
+ "# Set decimal printing to 3 decimal places\n",
+ "np.set_printoptions(precision=3, suppress=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7a5b1a35",
+ "metadata": {},
+ "source": [
+ "## Samuelson's model\n",
+ "\n",
+ "Let $t = 0, \\pm 1, \\pm 2, \\ldots$ index time.\n",
+ "\n",
+ "For $t = 1, 2, 3, \\ldots, T$ suppose that\n",
+ "\n",
+ "```{math}\n",
+ ":label: tswm_1\n",
+ "\n",
+ "y_{t} = \\alpha_{0} + \\alpha_{1} y_{t-1} + \\alpha_{2} y_{t-2}\n",
+ "```\n",
+ "\n",
+ "where we assume that $y_0$ and $y_{-1}$ are given numbers\n",
+ "that we take as *initial conditions*.\n",
+ "\n",
+ "In Samuelson's model, $y_t$ stood for **national income** or perhaps a different\n",
+ "measure of aggregate activity called **gross domestic product** (GDP) at time $t$.\n",
+ "\n",
+ "Equation {eq}`tswm_1` is called a *second-order linear difference equation*. It is called second order because it depends on two lags.\n",
+ "\n",
+ "But actually, it is a collection of $T$ simultaneous linear\n",
+ "equations in the $T$ variables $y_1, y_2, \\ldots, y_T$.\n",
+ "\n",
+ "```{note}\n",
+ "To be able to solve a second-order linear difference\n",
+ "equation, we require two *boundary conditions* that can take the form\n",
+ "either of two *initial conditions*, two *terminal conditions* or\n",
+ "possibly one of each.\n",
+ "```\n",
+ "\n",
+ "Let’s write our equations as a stacked system\n",
+ "\n",
+ "$$\n",
+ "\\underset{\\equiv A}{\\underbrace{\\left[\\begin{array}{cccccccc}\n",
+ "1 & 0 & 0 & 0 & \\cdots & 0 & 0 & 0\\\\\n",
+ "-\\alpha_{1} & 1 & 0 & 0 & \\cdots & 0 & 0 & 0\\\\\n",
+ "-\\alpha_{2} & -\\alpha_{1} & 1 & 0 & \\cdots & 0 & 0 & 0\\\\\n",
+ "0 & -\\alpha_{2} & -\\alpha_{1} & 1 & \\cdots & 0 & 0 & 0\\\\\n",
+ "\\vdots & \\vdots & \\vdots & \\vdots & \\cdots & \\vdots & \\vdots & \\vdots\\\\\n",
+ "0 & 0 & 0 & 0 & \\cdots & -\\alpha_{2} & -\\alpha_{1} & 1\n",
+ "\\end{array}\\right]}}\\left[\\begin{array}{c}\n",
+ "y_{1}\\\\\n",
+ "y_{2}\\\\\n",
+ "y_{3}\\\\\n",
+ "y_{4}\\\\\n",
+ "\\vdots\\\\\n",
+ "y_{T}\n",
+ "\\end{array}\\right]=\\underset{\\equiv b}{\\underbrace{\\left[\\begin{array}{c}\n",
+ "\\alpha_{0}+\\alpha_{1}y_{0}+\\alpha_{2}y_{-1}\\\\\n",
+ "\\alpha_{0}+\\alpha_{2}y_{0}\\\\\n",
+ "\\alpha_{0}\\\\\n",
+ "\\alpha_{0}\\\\\n",
+ "\\vdots\\\\\n",
+ "\\alpha_{0}\n",
+ "\\end{array}\\right]}}\n",
+ "$$\n",
+ "\n",
+ "or\n",
+ "\n",
+ "$$\n",
+ "A y = b\n",
+ "$$\n",
+ "\n",
+ "where\n",
+ "\n",
+ "$$\n",
+ "y = \\begin{bmatrix} y_1 \\cr y_2 \\cr \\vdots \\cr y_T \\end{bmatrix}\n",
+ "$$\n",
+ "\n",
+ "Evidently $y$ can be computed from\n",
+ "\n",
+ "$$\n",
+ "y = A^{-1} b\n",
+ "$$\n",
+ "\n",
+ "The vector $y$ is a complete time path $\\{y_t\\}_{t=1}^T$.\n",
+ "\n",
+ "Let’s put Python to work on an example that captures the flavor of\n",
+ "Samuelson’s multiplier-accelerator model.\n",
+ "\n",
+ "We'll set parameters equal to the same values we used in {doc}`intermediate:samuelson`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4b008ea3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "T = 80\n",
+ "\n",
+ "# parameters\n",
+ "α_0 = 10.0\n",
+ "α_1 = 1.53\n",
+ "α_2 = -.9\n",
+ "\n",
+ "y_neg1 = 28.0 # y_{-1}\n",
+ "y_0 = 24.0"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ac737ee0",
+ "metadata": {},
+ "source": [
+ "Now we construct $A$ and $b$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6b7a82d4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "A = np.identity(T) # The T x T identity matrix\n",
+ "\n",
+ "for i in range(T):\n",
+ "\n",
+ " if i-1 >= 0:\n",
+ " A[i, i-1] = -α_1\n",
+ "\n",
+ " if i-2 >= 0:\n",
+ " A[i, i-2] = -α_2\n",
+ "\n",
+ "b = np.full(T, α_0)\n",
+ "b[0] = α_0 + α_1 * y_0 + α_2 * y_neg1\n",
+ "b[1] = α_0 + α_2 * y_0"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4d0ccb9a",
+ "metadata": {},
+ "source": [
+ "Let’s look at the matrix $A$ and the vector $b$ for our\n",
+ "example."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9b3e612a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "A, b"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "dd180745",
+ "metadata": {},
+ "source": [
+ "Now let’s solve for the path of $y$.\n",
+ "\n",
+ "If $y_t$ is GNP at time $t$, then we have a version of\n",
+ "Samuelson’s model of the dynamics for GNP.\n",
+ "\n",
+ "To solve $y = A^{-1} b$ we can either invert $A$ directly, as in"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7adaee8e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "A_inv = np.linalg.inv(A)\n",
+ "\n",
+ "y = A_inv @ b"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b59d6b3c",
+ "metadata": {},
+ "source": [
+ "or we can use `np.linalg.solve`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3d33f1b5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "y_second_method = np.linalg.solve(A, b)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f7c44b68",
+ "metadata": {},
+ "source": [
+ "Here make sure the two methods give the same result, at least up to floating\n",
+ "point precision:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9edb5d47",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.allclose(y, y_second_method)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6b9b9b66",
+ "metadata": {},
+ "source": [
+ "$A$ is invertible as it is lower triangular and [its diagonal entries are non-zero](https://www.statlect.com/matrix-algebra/triangular-matrix)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b978f29f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Check if A is lower triangular\n",
+ "np.allclose(A, np.tril(A))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0277a4d4",
+ "metadata": {},
+ "source": [
+ "```{note}\n",
+ "In general, `np.linalg.solve` is more numerically stable than using\n",
+ "`np.linalg.inv` directly. \n",
+ "However, stability is not an issue for this small example. Moreover, we will\n",
+ "repeatedly use `A_inv` in what follows, so there is added value in computing\n",
+ "it directly.\n",
+ "```\n",
+ "\n",
+ "Now we can plot."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4b467a4a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.plot(np.arange(T)+1, y)\n",
+ "plt.xlabel('t')\n",
+ "plt.ylabel('y')\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "69011996",
+ "metadata": {},
+ "source": [
+ "The {ref}`*steady state*` value $y^*$ of $y_t$ is obtained by setting $y_t = y_{t-1} =\n",
+ "y_{t-2} = y^*$ in {eq}`tswm_1`, which yields\n",
+ "\n",
+ "$$\n",
+ "y^* = \\frac{\\alpha_{0}}{1 - \\alpha_{1} - \\alpha_{2}}\n",
+ "$$\n",
+ "\n",
+ "If we set the initial values to $y_{0} = y_{-1} = y^*$, then $y_{t}$ will be\n",
+ "constant:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e2646e84",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "y_star = α_0 / (1 - α_1 - α_2)\n",
+ "y_neg1_steady = y_star # y_{-1}\n",
+ "y_0_steady = y_star\n",
+ "\n",
+ "b_steady = np.full(T, α_0)\n",
+ "b_steady[0] = α_0 + α_1 * y_0_steady + α_2 * y_neg1_steady\n",
+ "b_steady[1] = α_0 + α_2 * y_0_steady"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e9e52d5d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "y_steady = A_inv @ b_steady"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e036b4b1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.plot(np.arange(T)+1, y_steady)\n",
+ "plt.xlabel('t')\n",
+ "plt.ylabel('y')\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6c82d911",
+ "metadata": {},
+ "source": [
+ "## Adding a random term\n",
+ "\n",
+ "To generate some excitement, we'll follow in the spirit of the great economists\n",
+ "[Eugen Slutsky](https://en.wikipedia.org/wiki/Eugen_Slutsky) and [Ragnar Frisch](https://en.wikipedia.org/wiki/Ragnar_Frisch) and replace our original second-order difference\n",
+ "equation with the following **second-order stochastic linear difference\n",
+ "equation**:\n",
+ "\n",
+ "```{math}\n",
+ ":label: tswm_2\n",
+ "\n",
+ "y_{t} = \\alpha_{0} + \\alpha_{1} y_{t-1} + \\alpha_{2} y_{t-2} + u_t\n",
+ "```\n",
+ "\n",
+ "where $u_{t} \\sim N\\left(0, \\sigma_{u}^{2}\\right)$ and is {ref}`IID `,\n",
+ "meaning independent and identically distributed.\n",
+ "\n",
+ "We’ll stack these $T$ equations into a system cast in terms of\n",
+ "matrix algebra.\n",
+ "\n",
+ "Let’s define the random vector\n",
+ "\n",
+ "$$\n",
+ "u=\\left[\\begin{array}{c}\n",
+ "u_{1}\\\\\n",
+ "u_{2}\\\\\n",
+ "\\vdots\\\\\n",
+ "u_{T}\n",
+ "\\end{array}\\right]\n",
+ "$$\n",
+ "\n",
+ "Where $A, b, y$ are defined as above, now assume that $y$ is\n",
+ "governed by the system\n",
+ "\n",
+ "$$\n",
+ "A y = b + u\n",
+ "$$ (eq:eqar)\n",
+ "\n",
+ "The solution for $y$ becomes\n",
+ "\n",
+ "$$\n",
+ "y = A^{-1} \\left(b + u\\right)\n",
+ "$$ (eq:eqma)\n",
+ "\n",
+ "Let’s try it out in Python."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "aa43dfed",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "σ_u = 2.\n",
+ "u = np.random.normal(0, σ_u, size=T)\n",
+ "y = A_inv @ (b + u)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "91004441",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.plot(np.arange(T)+1, y)\n",
+ "plt.xlabel('t')\n",
+ "plt.ylabel('y')\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2e31824b",
+ "metadata": {},
+ "source": [
+ "The above time series looks a lot like (detrended) GDP series for a\n",
+ "number of advanced countries in recent decades.\n",
+ "\n",
+ "We can simulate $N$ paths."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b67e9a23",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "N = 100\n",
+ "\n",
+ "for i in range(N):\n",
+ " col = cm.viridis(np.random.rand()) # Choose a random color from viridis\n",
+ " u = np.random.normal(0, σ_u, size=T)\n",
+ " y = A_inv @ (b + u)\n",
+ " plt.plot(np.arange(T)+1, y, lw=0.5, color=col)\n",
+ "\n",
+ "plt.xlabel('t')\n",
+ "plt.ylabel('y')\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c68b5439",
+ "metadata": {},
+ "source": [
+ "Also consider the case when $y_{0}$ and $y_{-1}$ are at\n",
+ "steady state."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2cb0f7fe",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "N = 100\n",
+ "\n",
+ "for i in range(N):\n",
+ " col = cm.viridis(np.random.rand()) # Choose a random color from viridis\n",
+ " u = np.random.normal(0, σ_u, size=T)\n",
+ " y_steady = A_inv @ (b_steady + u)\n",
+ " plt.plot(np.arange(T)+1, y_steady, lw=0.5, color=col)\n",
+ "\n",
+ "plt.xlabel('t')\n",
+ "plt.ylabel('y')\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7143140f",
+ "metadata": {},
+ "source": [
+ "## Computing population moments\n",
+ "\n",
+ "\n",
+ "We can apply standard formulas for multivariate normal distributions to compute the mean vector and covariance matrix\n",
+ "for our time series model\n",
+ "\n",
+ "$$\n",
+ "y = A^{-1} (b + u) .\n",
+ "$$\n",
+ "\n",
+ "You can read about multivariate normal distributions in this lecture [Multivariate Normal Distribution](https://python.quantecon.org/multivariate_normal.html).\n",
+ "\n",
+ "Let's write our model as \n",
+ "\n",
+ "$$ \n",
+ "y = \\tilde A (b + u)\n",
+ "$$\n",
+ "\n",
+ "where $\\tilde A = A^{-1}$.\n",
+ "\n",
+ "Because linear combinations of normal random variables are normal, we know that\n",
+ "\n",
+ "$$\n",
+ "y \\sim {\\mathcal N}(\\mu_y, \\Sigma_y)\n",
+ "$$\n",
+ "\n",
+ "where\n",
+ "\n",
+ "$$ \n",
+ "\\mu_y = \\tilde A b\n",
+ "$$\n",
+ "\n",
+ "and \n",
+ "\n",
+ "$$\n",
+ "\\Sigma_y = \\tilde A (\\sigma_u^2 I_{T \\times T} ) \\tilde A^T\n",
+ "$$\n",
+ "\n",
+ "Let's write a Python class that computes the mean vector $\\mu_y$ and covariance matrix $\\Sigma_y$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c8eb7726",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "class population_moments:\n",
+ " \"\"\"\n",
+ " Compute population moments μ_y, Σ_y.\n",
+ " ---------\n",
+ " Parameters:\n",
+ " α_0, α_1, α_2, T, y_neg1, y_0\n",
+ " \"\"\"\n",
+ " def __init__(self, α_0=10.0, \n",
+ " α_1=1.53, \n",
+ " α_2=-.9, \n",
+ " T=80, \n",
+ " y_neg1=28.0, \n",
+ " y_0=24.0, \n",
+ " σ_u=1):\n",
+ "\n",
+ " # compute A\n",
+ " A = np.identity(T)\n",
+ "\n",
+ " for i in range(T):\n",
+ " if i-1 >= 0:\n",
+ " A[i, i-1] = -α_1\n",
+ "\n",
+ " if i-2 >= 0:\n",
+ " A[i, i-2] = -α_2\n",
+ "\n",
+ " # compute b\n",
+ " b = np.full(T, α_0)\n",
+ " b[0] = α_0 + α_1 * y_0 + α_2 * y_neg1\n",
+ " b[1] = α_0 + α_2 * y_0\n",
+ "\n",
+ " # compute A inverse\n",
+ " A_inv = np.linalg.inv(A)\n",
+ "\n",
+ " self.A, self.b, self.A_inv, self.σ_u, self.T = A, b, A_inv, σ_u, T\n",
+ " \n",
+ " def sample_y(self, n):\n",
+ " \"\"\"\n",
+ " Give a sample of size n of y.\n",
+ " \"\"\"\n",
+ " A_inv, σ_u, b, T = self.A_inv, self.σ_u, self.b, self.T\n",
+ " us = np.random.normal(0, σ_u, size=[n, T])\n",
+ " ys = np.vstack([A_inv @ (b + u) for u in us])\n",
+ "\n",
+ " return ys\n",
+ "\n",
+ " def get_moments(self):\n",
+ " \"\"\"\n",
+ " Compute the population moments of y.\n",
+ " \"\"\"\n",
+ " A_inv, σ_u, b = self.A_inv, self.σ_u, self.b\n",
+ "\n",
+ " # compute μ_y\n",
+ " self.μ_y = A_inv @ b\n",
+ " self.Σ_y = σ_u**2 * (A_inv @ A_inv.T)\n",
+ " \n",
+ " return self.μ_y, self.Σ_y\n",
+ "\n",
+ "\n",
+ "series_process = population_moments()\n",
+ " \n",
+ "μ_y, Σ_y = series_process.get_moments()\n",
+ "A_inv = series_process.A_inv"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9ec7defd",
+ "metadata": {},
+ "source": [
+ "It is enlightening to study the $\\mu_y, \\Sigma_y$'s implied by various parameter values.\n",
+ "\n",
+ "Among other things, we can use the class to exhibit how **statistical stationarity** of $y$ prevails only for very special initial conditions. \n",
+ "\n",
+ "Let's begin by generating $N$ time realizations of $y$ plotting them together with population mean $\\mu_y$ ."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d08f93fe",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Plot mean\n",
+ "N = 100\n",
+ "\n",
+ "for i in range(N):\n",
+ " col = cm.viridis(np.random.rand()) # Choose a random color from viridis\n",
+ " ys = series_process.sample_y(N)\n",
+ " plt.plot(ys[i,:], lw=0.5, color=col)\n",
+ " plt.plot(μ_y, color='red')\n",
+ "\n",
+ "plt.xlabel('t')\n",
+ "plt.ylabel('y')\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "772dc503",
+ "metadata": {},
+ "source": [
+ "Visually, notice how the variance across realizations of $y_t$ decreases as $t$ increases.\n",
+ "\n",
+ "Let's plot the population variance of $y_t$ against $t$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "aa37a4da",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Plot variance\n",
+ "plt.plot(Σ_y.diagonal())\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d7926562",
+ "metadata": {},
+ "source": [
+ "Notice how the population variance increases and asymptotes."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "93498a14",
+ "metadata": {},
+ "source": [
+ "Let's print out the covariance matrix $\\Sigma_y$ for a time series $y$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5865fc35",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "series_process = population_moments(α_0=0, \n",
+ " α_1=.8, \n",
+ " α_2=0, \n",
+ " T=6,\n",
+ " y_neg1=0., \n",
+ " y_0=0., \n",
+ " σ_u=1)\n",
+ "\n",
+ "μ_y, Σ_y = series_process.get_moments()\n",
+ "print(\"μ_y = \", μ_y)\n",
+ "print(\"Σ_y = \\n\", Σ_y)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f7b4a562",
+ "metadata": {},
+ "source": [
+ "Notice that the covariance between $y_t$ and $y_{t-1}$ -- the elements on the superdiagonal -- are *not* identical.\n",
+ "\n",
+ "This is an indication that the time series represented by our $y$ vector is not **stationary**. \n",
+ "\n",
+ "To make it stationary, we'd have to alter our system so that our *initial conditions* $(y_0, y_{-1})$ are not fixed numbers but instead a jointly normally distributed random vector with a particular mean and covariance matrix.\n",
+ "\n",
+ "We describe how to do that in [Linear State Space Models](https://python.quantecon.org/linear_models.html).\n",
+ "\n",
+ "But just to set the stage for that analysis, let's print out the bottom right corner of $\\Sigma_y$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8349c6af",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "series_process = population_moments()\n",
+ "μ_y, Σ_y = series_process.get_moments()\n",
+ "\n",
+ "print(\"bottom right corner of Σ_y = \\n\", Σ_y[72:,72:])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f8618ba8",
+ "metadata": {},
+ "source": [
+ "Please notice how the subdiagonal and superdiagonal elements seem to have converged.\n",
+ "\n",
+ "This is an indication that our process is asymptotically stationary.\n",
+ "\n",
+ "You can read about stationarity of more general linear time series models in this lecture [Linear State Space Models](https://python.quantecon.org/linear_models.html).\n",
+ "\n",
+ "There is a lot to be learned about the process by staring at the off diagonal elements of $\\Sigma_y$ corresponding to different time periods $t$, but we resist the temptation to do so here."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2afae198",
+ "metadata": {},
+ "source": [
+ "## Moving average representation\n",
+ "\n",
+ "Let's print out $A^{-1}$ and stare at its structure \n",
+ "\n",
+ " * is it triangular or almost triangular or $\\ldots$ ?\n",
+ "\n",
+ "To study the structure of $A^{-1}$, we shall print just up to $3$ decimals.\n",
+ "\n",
+ "Let's begin by printing out just the upper left hand corner of $A^{-1}$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ef8fb28a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(A_inv[0:7,0:7])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "afa30a0a",
+ "metadata": {},
+ "source": [
+ "Evidently, $A^{-1}$ is a lower triangular matrix. \n",
+ "\n",
+ "Notice how every row ends with the previous row's pre-diagonal entries.\n",
+ "\n",
+ "Since $A^{-1}$ is lower triangular, each row represents $ y_t$ for a particular $t$ as the sum of \n",
+ "- a time-dependent function $A^{-1} b$ of the initial conditions incorporated in $b$, and \n",
+ "- a weighted sum of current and past values of the IID shocks $\\{u_t\\}$.\n",
+ "\n",
+ "Thus, let $\\tilde{A}=A^{-1}$. \n",
+ "\n",
+ "Evidently, for $t\\geq0$,\n",
+ "\n",
+ "$$\n",
+ "y_{t+1}=\\sum_{i=1}^{t+1}\\tilde{A}_{t+1,i}b_{i}+\\sum_{i=1}^{t}\\tilde{A}_{t+1,i}u_{i}+u_{t+1}\n",
+ "$$\n",
+ "\n",
+ "This is a **moving average** representation with time-varying coefficients.\n",
+ "\n",
+ "Just as system {eq}`eq:eqma` constitutes a \n",
+ "**moving average** representation for $y$, system {eq}`eq:eqar` constitutes an **autoregressive** representation for $y$.\n",
+ "\n",
+ "## A forward looking model\n",
+ "\n",
+ "Samuelson’s model is *backward looking* in the sense that we give it *initial conditions* and let it\n",
+ "run.\n",
+ "\n",
+ "Let’s now turn to model that is *forward looking*.\n",
+ "\n",
+ "We apply similar linear algebra machinery to study a *perfect\n",
+ "foresight* model widely used as a benchmark in macroeconomics and\n",
+ "finance.\n",
+ "\n",
+ "As an example, we suppose that $p_t$ is the price of a stock and\n",
+ "that $y_t$ is its dividend.\n",
+ "\n",
+ "We assume that $y_t$ is determined by second-order difference\n",
+ "equation that we analyzed just above, so that\n",
+ "\n",
+ "$$\n",
+ "y = A^{-1} \\left(b + u\\right)\n",
+ "$$\n",
+ "\n",
+ "Our *perfect foresight* model of stock prices is\n",
+ "\n",
+ "$$\n",
+ "p_{t} = \\sum_{j=0}^{T-t} \\beta^{j} y_{t+j}, \\quad \\beta \\in (0,1)\n",
+ "$$\n",
+ "\n",
+ "where $\\beta$ is a discount factor.\n",
+ "\n",
+ "The model asserts that the price of the stock at $t$ equals the\n",
+ "discounted present values of the (perfectly foreseen) future dividends.\n",
+ "\n",
+ "Form\n",
+ "\n",
+ "$$\n",
+ "\\underset{\\equiv p}{\\underbrace{\\left[\\begin{array}{c}\n",
+ "p_{1}\\\\\n",
+ "p_{2}\\\\\n",
+ "p_{3}\\\\\n",
+ "\\vdots\\\\\n",
+ "p_{T}\n",
+ "\\end{array}\\right]}}=\\underset{\\equiv B}{\\underbrace{\\left[\\begin{array}{ccccc}\n",
+ "1 & \\beta & \\beta^{2} & \\cdots & \\beta^{T-1}\\\\\n",
+ "0 & 1 & \\beta & \\cdots & \\beta^{T-2}\\\\\n",
+ "0 & 0 & 1 & \\cdots & \\beta^{T-3}\\\\\n",
+ "\\vdots & \\vdots & \\vdots & \\vdots & \\vdots\\\\\n",
+ "0 & 0 & 0 & \\cdots & 1\n",
+ "\\end{array}\\right]}}\\left[\\begin{array}{c}\n",
+ "y_{1}\\\\\n",
+ "y_{2}\\\\\n",
+ "y_{3}\\\\\n",
+ "\\vdots\\\\\n",
+ "y_{T}\n",
+ "\\end{array}\\right]\n",
+ "$$"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "0a6bda0f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "β = .96"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "dc364592",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# construct B\n",
+ "B = np.zeros((T, T))\n",
+ "\n",
+ "for i in range(T):\n",
+ " B[i, i:] = β ** np.arange(0, T-i)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "51b51578",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(B)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e55ef156",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "σ_u = 0.\n",
+ "u = np.random.normal(0, σ_u, size=T)\n",
+ "y = A_inv @ (b + u)\n",
+ "y_steady = A_inv @ (b_steady + u)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9eba6d30",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "p = B @ y"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6e504cc4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.plot(np.arange(0, T)+1, y, label='y')\n",
+ "plt.plot(np.arange(0, T)+1, p, label='p')\n",
+ "plt.xlabel('t')\n",
+ "plt.ylabel('y/p')\n",
+ "plt.legend()\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1de84b0a",
+ "metadata": {},
+ "source": [
+ "Can you explain why the trend of the price is downward over time?\n",
+ "\n",
+ "Also consider the case when $y_{0}$ and $y_{-1}$ are at the\n",
+ "steady state."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6574e326",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "p_steady = B @ y_steady\n",
+ "\n",
+ "plt.plot(np.arange(0, T)+1, y_steady, label='y')\n",
+ "plt.plot(np.arange(0, T)+1, p_steady, label='p')\n",
+ "plt.xlabel('t')\n",
+ "plt.ylabel('y/p')\n",
+ "plt.legend()\n",
+ "\n",
+ "plt.show()"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.16.1"
+ }
+ },
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "source_map": [
+ 12,
+ 48,
+ 58,
+ 142,
+ 152,
+ 156,
+ 170,
+ 175,
+ 177,
+ 186,
+ 190,
+ 194,
+ 196,
+ 201,
+ 203,
+ 207,
+ 210,
+ 222,
+ 228,
+ 240,
+ 250,
+ 254,
+ 260,
+ 307,
+ 313,
+ 319,
+ 326,
+ 339,
+ 344,
+ 357,
+ 399,
+ 462,
+ 470,
+ 484,
+ 490,
+ 494,
+ 498,
+ 502,
+ 514,
+ 526,
+ 531,
+ 541,
+ 553,
+ 555,
+ 634,
+ 638,
+ 646,
+ 650,
+ 657,
+ 661,
+ 669,
+ 676
+ ]
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/time_series_with_matrices.md b/book/_build/html/_sources/time_series_with_matrices.md
new file mode 100644
index 0000000..e73566c
--- /dev/null
+++ b/book/_build/html/_sources/time_series_with_matrices.md
@@ -0,0 +1,686 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.16.1
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+(time_series_with_matrices)=
+```{raw} jupyter
+
+```
+
+# Univariate Time Series with Matrix Algebra
+
+## Overview
+
+This lecture uses matrices to solve some linear difference equations.
+
+As a running example, we’ll study a **second-order linear difference
+equation** that was the key technical tool in Paul Samuelson’s 1939
+article {cite}`Samuelson1939` that introduced the *multiplier-accelerator model*.
+
+This model became the workhorse that powered early econometric versions of
+Keynesian macroeconomic models in the United States.
+
+You can read about the details of that model in {doc}`intermediate:samuelson`.
+
+(That lecture also describes some technicalities about second-order linear difference equations.)
+
+In this lecture, we'll also learn about an **autoregressive** representation and a **moving average** representation of a non-stationary
+univariate time series $\{y_t\}_{t=0}^T$.
+
+We'll also study a "perfect foresight" model of stock prices that involves solving
+a "forward-looking" linear difference equation.
+
+We will use the following imports:
+
+```{code-cell} ipython3
+import numpy as np
+import matplotlib.pyplot as plt
+from matplotlib import cm
+
+# Custom figsize for this lecture
+plt.rcParams["figure.figsize"] = (11, 5)
+
+# Set decimal printing to 3 decimal places
+np.set_printoptions(precision=3, suppress=True)
+```
+
+## Samuelson's model
+
+Let $t = 0, \pm 1, \pm 2, \ldots$ index time.
+
+For $t = 1, 2, 3, \ldots, T$ suppose that
+
+```{math}
+:label: tswm_1
+
+y_{t} = \alpha_{0} + \alpha_{1} y_{t-1} + \alpha_{2} y_{t-2}
+```
+
+where we assume that $y_0$ and $y_{-1}$ are given numbers
+that we take as *initial conditions*.
+
+In Samuelson's model, $y_t$ stood for **national income** or perhaps a different
+measure of aggregate activity called **gross domestic product** (GDP) at time $t$.
+
+Equation {eq}`tswm_1` is called a *second-order linear difference equation*. It is called second order because it depends on two lags.
+
+But actually, it is a collection of $T$ simultaneous linear
+equations in the $T$ variables $y_1, y_2, \ldots, y_T$.
+
+```{note}
+To be able to solve a second-order linear difference
+equation, we require two *boundary conditions* that can take the form
+either of two *initial conditions*, two *terminal conditions* or
+possibly one of each.
+```
+
+Let’s write our equations as a stacked system
+
+$$
+\underset{\equiv A}{\underbrace{\left[\begin{array}{cccccccc}
+1 & 0 & 0 & 0 & \cdots & 0 & 0 & 0\\
+-\alpha_{1} & 1 & 0 & 0 & \cdots & 0 & 0 & 0\\
+-\alpha_{2} & -\alpha_{1} & 1 & 0 & \cdots & 0 & 0 & 0\\
+0 & -\alpha_{2} & -\alpha_{1} & 1 & \cdots & 0 & 0 & 0\\
+\vdots & \vdots & \vdots & \vdots & \cdots & \vdots & \vdots & \vdots\\
+0 & 0 & 0 & 0 & \cdots & -\alpha_{2} & -\alpha_{1} & 1
+\end{array}\right]}}\left[\begin{array}{c}
+y_{1}\\
+y_{2}\\
+y_{3}\\
+y_{4}\\
+\vdots\\
+y_{T}
+\end{array}\right]=\underset{\equiv b}{\underbrace{\left[\begin{array}{c}
+\alpha_{0}+\alpha_{1}y_{0}+\alpha_{2}y_{-1}\\
+\alpha_{0}+\alpha_{2}y_{0}\\
+\alpha_{0}\\
+\alpha_{0}\\
+\vdots\\
+\alpha_{0}
+\end{array}\right]}}
+$$
+
+or
+
+$$
+A y = b
+$$
+
+where
+
+$$
+y = \begin{bmatrix} y_1 \cr y_2 \cr \vdots \cr y_T \end{bmatrix}
+$$
+
+Evidently $y$ can be computed from
+
+$$
+y = A^{-1} b
+$$
+
+The vector $y$ is a complete time path $\{y_t\}_{t=1}^T$.
+
+Let’s put Python to work on an example that captures the flavor of
+Samuelson’s multiplier-accelerator model.
+
+We'll set parameters equal to the same values we used in {doc}`intermediate:samuelson`.
+
+```{code-cell} ipython3
+T = 80
+
+# parameters
+α_0 = 10.0
+α_1 = 1.53
+α_2 = -.9
+
+y_neg1 = 28.0 # y_{-1}
+y_0 = 24.0
+```
+
+Now we construct $A$ and $b$.
+
+```{code-cell} ipython3
+A = np.identity(T) # The T x T identity matrix
+
+for i in range(T):
+
+ if i-1 >= 0:
+ A[i, i-1] = -α_1
+
+ if i-2 >= 0:
+ A[i, i-2] = -α_2
+
+b = np.full(T, α_0)
+b[0] = α_0 + α_1 * y_0 + α_2 * y_neg1
+b[1] = α_0 + α_2 * y_0
+```
+
+Let’s look at the matrix $A$ and the vector $b$ for our
+example.
+
+```{code-cell} ipython3
+A, b
+```
+
+Now let’s solve for the path of $y$.
+
+If $y_t$ is GNP at time $t$, then we have a version of
+Samuelson’s model of the dynamics for GNP.
+
+To solve $y = A^{-1} b$ we can either invert $A$ directly, as in
+
+```{code-cell} ipython3
+A_inv = np.linalg.inv(A)
+
+y = A_inv @ b
+```
+
+or we can use `np.linalg.solve`:
+
+```{code-cell} ipython3
+y_second_method = np.linalg.solve(A, b)
+```
+
+Here make sure the two methods give the same result, at least up to floating
+point precision:
+
+```{code-cell} ipython3
+np.allclose(y, y_second_method)
+```
+
+$A$ is invertible as it is lower triangular and [its diagonal entries are non-zero](https://www.statlect.com/matrix-algebra/triangular-matrix)
+
+```{code-cell} ipython3
+# Check if A is lower triangular
+np.allclose(A, np.tril(A))
+```
+
+```{note}
+In general, `np.linalg.solve` is more numerically stable than using
+`np.linalg.inv` directly.
+However, stability is not an issue for this small example. Moreover, we will
+repeatedly use `A_inv` in what follows, so there is added value in computing
+it directly.
+```
+
+Now we can plot.
+
+```{code-cell} ipython3
+plt.plot(np.arange(T)+1, y)
+plt.xlabel('t')
+plt.ylabel('y')
+
+plt.show()
+```
+
+The {ref}`*steady state*` value $y^*$ of $y_t$ is obtained by setting $y_t = y_{t-1} =
+y_{t-2} = y^*$ in {eq}`tswm_1`, which yields
+
+$$
+y^* = \frac{\alpha_{0}}{1 - \alpha_{1} - \alpha_{2}}
+$$
+
+If we set the initial values to $y_{0} = y_{-1} = y^*$, then $y_{t}$ will be
+constant:
+
+```{code-cell} ipython3
+y_star = α_0 / (1 - α_1 - α_2)
+y_neg1_steady = y_star # y_{-1}
+y_0_steady = y_star
+
+b_steady = np.full(T, α_0)
+b_steady[0] = α_0 + α_1 * y_0_steady + α_2 * y_neg1_steady
+b_steady[1] = α_0 + α_2 * y_0_steady
+```
+
+```{code-cell} ipython3
+y_steady = A_inv @ b_steady
+```
+
+```{code-cell} ipython3
+plt.plot(np.arange(T)+1, y_steady)
+plt.xlabel('t')
+plt.ylabel('y')
+
+plt.show()
+```
+
+## Adding a random term
+
+To generate some excitement, we'll follow in the spirit of the great economists
+[Eugen Slutsky](https://en.wikipedia.org/wiki/Eugen_Slutsky) and [Ragnar Frisch](https://en.wikipedia.org/wiki/Ragnar_Frisch) and replace our original second-order difference
+equation with the following **second-order stochastic linear difference
+equation**:
+
+```{math}
+:label: tswm_2
+
+y_{t} = \alpha_{0} + \alpha_{1} y_{t-1} + \alpha_{2} y_{t-2} + u_t
+```
+
+where $u_{t} \sim N\left(0, \sigma_{u}^{2}\right)$ and is {ref}`IID `,
+meaning independent and identically distributed.
+
+We’ll stack these $T$ equations into a system cast in terms of
+matrix algebra.
+
+Let’s define the random vector
+
+$$
+u=\left[\begin{array}{c}
+u_{1}\\
+u_{2}\\
+\vdots\\
+u_{T}
+\end{array}\right]
+$$
+
+Where $A, b, y$ are defined as above, now assume that $y$ is
+governed by the system
+
+$$
+A y = b + u
+$$ (eq:eqar)
+
+The solution for $y$ becomes
+
+$$
+y = A^{-1} \left(b + u\right)
+$$ (eq:eqma)
+
+Let’s try it out in Python.
+
+```{code-cell} ipython3
+σ_u = 2.
+u = np.random.normal(0, σ_u, size=T)
+y = A_inv @ (b + u)
+```
+
+```{code-cell} ipython3
+plt.plot(np.arange(T)+1, y)
+plt.xlabel('t')
+plt.ylabel('y')
+
+plt.show()
+```
+
+The above time series looks a lot like (detrended) GDP series for a
+number of advanced countries in recent decades.
+
+We can simulate $N$ paths.
+
+```{code-cell} ipython3
+N = 100
+
+for i in range(N):
+ col = cm.viridis(np.random.rand()) # Choose a random color from viridis
+ u = np.random.normal(0, σ_u, size=T)
+ y = A_inv @ (b + u)
+ plt.plot(np.arange(T)+1, y, lw=0.5, color=col)
+
+plt.xlabel('t')
+plt.ylabel('y')
+
+plt.show()
+```
+
+Also consider the case when $y_{0}$ and $y_{-1}$ are at
+steady state.
+
+```{code-cell} ipython3
+N = 100
+
+for i in range(N):
+ col = cm.viridis(np.random.rand()) # Choose a random color from viridis
+ u = np.random.normal(0, σ_u, size=T)
+ y_steady = A_inv @ (b_steady + u)
+ plt.plot(np.arange(T)+1, y_steady, lw=0.5, color=col)
+
+plt.xlabel('t')
+plt.ylabel('y')
+
+plt.show()
+```
+
+## Computing population moments
+
+
+We can apply standard formulas for multivariate normal distributions to compute the mean vector and covariance matrix
+for our time series model
+
+$$
+y = A^{-1} (b + u) .
+$$
+
+You can read about multivariate normal distributions in this lecture [Multivariate Normal Distribution](https://python.quantecon.org/multivariate_normal.html).
+
+Let's write our model as
+
+$$
+y = \tilde A (b + u)
+$$
+
+where $\tilde A = A^{-1}$.
+
+Because linear combinations of normal random variables are normal, we know that
+
+$$
+y \sim {\mathcal N}(\mu_y, \Sigma_y)
+$$
+
+where
+
+$$
+\mu_y = \tilde A b
+$$
+
+and
+
+$$
+\Sigma_y = \tilde A (\sigma_u^2 I_{T \times T} ) \tilde A^T
+$$
+
+Let's write a Python class that computes the mean vector $\mu_y$ and covariance matrix $\Sigma_y$.
+
+```{code-cell} ipython3
+class population_moments:
+ """
+ Compute population moments μ_y, Σ_y.
+ ---------
+ Parameters:
+ α_0, α_1, α_2, T, y_neg1, y_0
+ """
+ def __init__(self, α_0=10.0,
+ α_1=1.53,
+ α_2=-.9,
+ T=80,
+ y_neg1=28.0,
+ y_0=24.0,
+ σ_u=1):
+
+ # compute A
+ A = np.identity(T)
+
+ for i in range(T):
+ if i-1 >= 0:
+ A[i, i-1] = -α_1
+
+ if i-2 >= 0:
+ A[i, i-2] = -α_2
+
+ # compute b
+ b = np.full(T, α_0)
+ b[0] = α_0 + α_1 * y_0 + α_2 * y_neg1
+ b[1] = α_0 + α_2 * y_0
+
+ # compute A inverse
+ A_inv = np.linalg.inv(A)
+
+ self.A, self.b, self.A_inv, self.σ_u, self.T = A, b, A_inv, σ_u, T
+
+ def sample_y(self, n):
+ """
+ Give a sample of size n of y.
+ """
+ A_inv, σ_u, b, T = self.A_inv, self.σ_u, self.b, self.T
+ us = np.random.normal(0, σ_u, size=[n, T])
+ ys = np.vstack([A_inv @ (b + u) for u in us])
+
+ return ys
+
+ def get_moments(self):
+ """
+ Compute the population moments of y.
+ """
+ A_inv, σ_u, b = self.A_inv, self.σ_u, self.b
+
+ # compute μ_y
+ self.μ_y = A_inv @ b
+ self.Σ_y = σ_u**2 * (A_inv @ A_inv.T)
+
+ return self.μ_y, self.Σ_y
+
+
+series_process = population_moments()
+
+μ_y, Σ_y = series_process.get_moments()
+A_inv = series_process.A_inv
+```
+
+It is enlightening to study the $\mu_y, \Sigma_y$'s implied by various parameter values.
+
+Among other things, we can use the class to exhibit how **statistical stationarity** of $y$ prevails only for very special initial conditions.
+
+Let's begin by generating $N$ time realizations of $y$ plotting them together with population mean $\mu_y$ .
+
+```{code-cell} ipython3
+# Plot mean
+N = 100
+
+for i in range(N):
+ col = cm.viridis(np.random.rand()) # Choose a random color from viridis
+ ys = series_process.sample_y(N)
+ plt.plot(ys[i,:], lw=0.5, color=col)
+ plt.plot(μ_y, color='red')
+
+plt.xlabel('t')
+plt.ylabel('y')
+
+plt.show()
+```
+
+Visually, notice how the variance across realizations of $y_t$ decreases as $t$ increases.
+
+Let's plot the population variance of $y_t$ against $t$.
+
+```{code-cell} ipython3
+# Plot variance
+plt.plot(Σ_y.diagonal())
+plt.show()
+```
+
+Notice how the population variance increases and asymptotes.
+
++++
+
+Let's print out the covariance matrix $\Sigma_y$ for a time series $y$.
+
+```{code-cell} ipython3
+series_process = population_moments(α_0=0,
+ α_1=.8,
+ α_2=0,
+ T=6,
+ y_neg1=0.,
+ y_0=0.,
+ σ_u=1)
+
+μ_y, Σ_y = series_process.get_moments()
+print("μ_y = ", μ_y)
+print("Σ_y = \n", Σ_y)
+```
+
+Notice that the covariance between $y_t$ and $y_{t-1}$ -- the elements on the superdiagonal -- are *not* identical.
+
+This is an indication that the time series represented by our $y$ vector is not **stationary**.
+
+To make it stationary, we'd have to alter our system so that our *initial conditions* $(y_0, y_{-1})$ are not fixed numbers but instead a jointly normally distributed random vector with a particular mean and covariance matrix.
+
+We describe how to do that in [Linear State Space Models](https://python.quantecon.org/linear_models.html).
+
+But just to set the stage for that analysis, let's print out the bottom right corner of $\Sigma_y$.
+
+```{code-cell} ipython3
+series_process = population_moments()
+μ_y, Σ_y = series_process.get_moments()
+
+print("bottom right corner of Σ_y = \n", Σ_y[72:,72:])
+```
+
+Please notice how the subdiagonal and superdiagonal elements seem to have converged.
+
+This is an indication that our process is asymptotically stationary.
+
+You can read about stationarity of more general linear time series models in this lecture [Linear State Space Models](https://python.quantecon.org/linear_models.html).
+
+There is a lot to be learned about the process by staring at the off diagonal elements of $\Sigma_y$ corresponding to different time periods $t$, but we resist the temptation to do so here.
+
++++
+
+## Moving average representation
+
+Let's print out $A^{-1}$ and stare at its structure
+
+ * is it triangular or almost triangular or $\ldots$ ?
+
+To study the structure of $A^{-1}$, we shall print just up to $3$ decimals.
+
+Let's begin by printing out just the upper left hand corner of $A^{-1}$.
+
+```{code-cell} ipython3
+print(A_inv[0:7,0:7])
+```
+
+Evidently, $A^{-1}$ is a lower triangular matrix.
+
+Notice how every row ends with the previous row's pre-diagonal entries.
+
+Since $A^{-1}$ is lower triangular, each row represents $ y_t$ for a particular $t$ as the sum of
+- a time-dependent function $A^{-1} b$ of the initial conditions incorporated in $b$, and
+- a weighted sum of current and past values of the IID shocks $\{u_t\}$.
+
+Thus, let $\tilde{A}=A^{-1}$.
+
+Evidently, for $t\geq0$,
+
+$$
+y_{t+1}=\sum_{i=1}^{t+1}\tilde{A}_{t+1,i}b_{i}+\sum_{i=1}^{t}\tilde{A}_{t+1,i}u_{i}+u_{t+1}
+$$
+
+This is a **moving average** representation with time-varying coefficients.
+
+Just as system {eq}`eq:eqma` constitutes a
+**moving average** representation for $y$, system {eq}`eq:eqar` constitutes an **autoregressive** representation for $y$.
+
+## A forward looking model
+
+Samuelson’s model is *backward looking* in the sense that we give it *initial conditions* and let it
+run.
+
+Let’s now turn to model that is *forward looking*.
+
+We apply similar linear algebra machinery to study a *perfect
+foresight* model widely used as a benchmark in macroeconomics and
+finance.
+
+As an example, we suppose that $p_t$ is the price of a stock and
+that $y_t$ is its dividend.
+
+We assume that $y_t$ is determined by second-order difference
+equation that we analyzed just above, so that
+
+$$
+y = A^{-1} \left(b + u\right)
+$$
+
+Our *perfect foresight* model of stock prices is
+
+$$
+p_{t} = \sum_{j=0}^{T-t} \beta^{j} y_{t+j}, \quad \beta \in (0,1)
+$$
+
+where $\beta$ is a discount factor.
+
+The model asserts that the price of the stock at $t$ equals the
+discounted present values of the (perfectly foreseen) future dividends.
+
+Form
+
+$$
+\underset{\equiv p}{\underbrace{\left[\begin{array}{c}
+p_{1}\\
+p_{2}\\
+p_{3}\\
+\vdots\\
+p_{T}
+\end{array}\right]}}=\underset{\equiv B}{\underbrace{\left[\begin{array}{ccccc}
+1 & \beta & \beta^{2} & \cdots & \beta^{T-1}\\
+0 & 1 & \beta & \cdots & \beta^{T-2}\\
+0 & 0 & 1 & \cdots & \beta^{T-3}\\
+\vdots & \vdots & \vdots & \vdots & \vdots\\
+0 & 0 & 0 & \cdots & 1
+\end{array}\right]}}\left[\begin{array}{c}
+y_{1}\\
+y_{2}\\
+y_{3}\\
+\vdots\\
+y_{T}
+\end{array}\right]
+$$
+
+```{code-cell} ipython3
+β = .96
+```
+
+```{code-cell} ipython3
+# construct B
+B = np.zeros((T, T))
+
+for i in range(T):
+ B[i, i:] = β ** np.arange(0, T-i)
+```
+
+```{code-cell} ipython3
+print(B)
+```
+
+```{code-cell} ipython3
+σ_u = 0.
+u = np.random.normal(0, σ_u, size=T)
+y = A_inv @ (b + u)
+y_steady = A_inv @ (b_steady + u)
+```
+
+```{code-cell} ipython3
+p = B @ y
+```
+
+```{code-cell} ipython3
+plt.plot(np.arange(0, T)+1, y, label='y')
+plt.plot(np.arange(0, T)+1, p, label='p')
+plt.xlabel('t')
+plt.ylabel('y/p')
+plt.legend()
+
+plt.show()
+```
+
+Can you explain why the trend of the price is downward over time?
+
+Also consider the case when $y_{0}$ and $y_{-1}$ are at the
+steady state.
+
+```{code-cell} ipython3
+p_steady = B @ y_steady
+
+plt.plot(np.arange(0, T)+1, y_steady, label='y')
+plt.plot(np.arange(0, T)+1, p_steady, label='p')
+plt.xlabel('t')
+plt.ylabel('y/p')
+plt.legend()
+
+plt.show()
+```
diff --git a/content/lectures/troubleshooting.ipynb b/book/_build/html/_sources/troubleshooting.ipynb
similarity index 92%
rename from content/lectures/troubleshooting.ipynb
rename to book/_build/html/_sources/troubleshooting.ipynb
index 1e10fc7..17a53ec 100644
--- a/content/lectures/troubleshooting.ipynb
+++ b/book/_build/html/_sources/troubleshooting.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "f553b263",
+ "id": "a318fb62",
"metadata": {},
"source": [
"(troubleshooting)=\n",
@@ -16,13 +16,9 @@
"\n",
"# Troubleshooting\n",
"\n",
- "```{contents} Contents\n",
- ":depth: 2\n",
- "```\n",
- "\n",
"This page is for readers experiencing errors when running the code from the lectures.\n",
"\n",
- "## Fixing Your Local Environment\n",
+ "## Fixing your local environment\n",
"\n",
"The basic assumption of the lectures is that code in a lecture should execute whenever\n",
"\n",
@@ -58,7 +54,7 @@
"We like getting feedback on the lectures so please don't hesitate to get in\n",
"touch.\n",
"\n",
- "## Reporting an Issue\n",
+ "## Reporting an issue\n",
"\n",
"One way to give feedback is to raise an issue through our [issue tracker](https://github.com/QuantEcon/lecture-python/issues).\n",
"\n",
@@ -72,12 +68,21 @@
}
],
"metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst"
+ }
+ },
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
- }
+ },
+ "source_map": [
+ 10
+ ]
},
"nbformat": 4,
"nbformat_minor": 5
-}
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/troubleshooting.md b/book/_build/html/_sources/troubleshooting.md
new file mode 100644
index 0000000..7bc907a
--- /dev/null
+++ b/book/_build/html/_sources/troubleshooting.md
@@ -0,0 +1,71 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+kernelspec:
+ display_name: Python 3
+ language: python
+ name: python3
+---
+
+(troubleshooting)=
+```{raw} html
+
+```
+
+# Troubleshooting
+
+This page is for readers experiencing errors when running the code from the lectures.
+
+## Fixing your local environment
+
+The basic assumption of the lectures is that code in a lecture should execute whenever
+
+1. it is executed in a Jupyter notebook and
+1. the notebook is running on a machine with the latest version of Anaconda Python.
+
+You have installed Anaconda, haven't you, following the instructions in [this lecture](https://python-programming.quantecon.org/getting_started.html)?
+
+Assuming that you have, the most common source of problems for our readers is that their Anaconda distribution is not up to date.
+
+[Here's a useful article](https://www.anaconda.com/blog/keeping-anaconda-date)
+on how to update Anaconda.
+
+Another option is to simply remove Anaconda and reinstall.
+
+You also need to keep the external code libraries, such as [QuantEcon.py](https://quantecon.org/quantecon-py) up to date.
+
+For this task you can either
+
+* use conda install -y quantecon on the command line, or
+* execute !conda install -y quantecon within a Jupyter notebook.
+
+If your local environment is still not working you can do two things.
+
+First, you can use a remote machine instead, by clicking on the Launch Notebook icon available for each lecture
+
+```{image} _static/lecture_specific/troubleshooting/launch.png
+
+```
+
+Second, you can report an issue, so we can try to fix your local set up.
+
+We like getting feedback on the lectures so please don't hesitate to get in
+touch.
+
+## Reporting an issue
+
+One way to give feedback is to raise an issue through our [issue tracker](https://github.com/QuantEcon/lecture-python/issues).
+
+Please be as specific as possible. Tell us where the problem is and as much
+detail about your local set up as you can provide.
+
+Another feedback option is to use our [discourse forum](https://discourse.quantecon.org/).
+
+Finally, you can provide direct feedback to [contact@quantecon.org](mailto:contact@quantecon.org)
+
diff --git a/book/_build/html/_sources/unpleasant.ipynb b/book/_build/html/_sources/unpleasant.ipynb
new file mode 100644
index 0000000..171d5ba
--- /dev/null
+++ b/book/_build/html/_sources/unpleasant.ipynb
@@ -0,0 +1,622 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "ba348dcc",
+ "metadata": {},
+ "source": [
+ "# Some Unpleasant Monetarist Arithmetic \n",
+ "\n",
+ "## Overview\n",
+ "\n",
+ "\n",
+ "This lecture builds on concepts and issues introduced in {doc}`money_inflation`.\n",
+ "\n",
+ "That lecture describes stationary equilibria that reveal a [*Laffer curve*](https://en.wikipedia.org/wiki/Laffer_curve) in the inflation tax rate and the associated stationary rate of return \n",
+ "on currency. \n",
+ "\n",
+ "In this lecture we study a situation in which a stationary equilibrium prevails after date $T > 0$, but not before then. \n",
+ "\n",
+ "For $t=0, \\ldots, T-1$, the money supply, price level, and interest-bearing government debt vary along a transition path that ends at $t=T$.\n",
+ "\n",
+ "During this transition, the ratio of the real balances $\\frac{m_{t+1}}{{p_t}}$ to indexed one-period government bonds $\\tilde R B_{t-1}$ maturing at time $t$ decreases each period. \n",
+ "\n",
+ "This has consequences for the **gross-of-interest** government deficit that must be financed by printing money for times $t \\geq T$. \n",
+ "\n",
+ "The critical **money-to-bonds** ratio stabilizes only at time $T$ and afterwards.\n",
+ "\n",
+ "And the larger is $T$, the higher is the gross-of-interest government deficit that must be financed\n",
+ "by printing money at times $t \\geq T$. \n",
+ "\n",
+ "These outcomes are the essential finding of Sargent and Wallace's \"unpleasant monetarist arithmetic\" {cite}`sargent1981`.\n",
+ "\n",
+ "That lecture described supplies and demands for money that appear in lecture.\n",
+ "\n",
+ "It also characterized the steady state equilibrium from which we work backwards in this lecture. \n",
+ "\n",
+ "In addition to learning about \"unpleasant monetarist arithmetic\", in this lecture we'll learn how to implement a [*fixed point*](https://en.wikipedia.org/wiki/Fixed_point_(mathematics)) algorithm for computing an initial price level.\n",
+ "\n",
+ "\n",
+ "## Setup\n",
+ "\n",
+ "Let's start with quick reminders of the model's components set out in {doc}`money_inflation`.\n",
+ "\n",
+ "Please consult that lecture for more details and Python code that we'll also use in this lecture.\n",
+ "\n",
+ "For $t \\geq 1$, **real balances** evolve according to\n",
+ "\n",
+ "\n",
+ "$$\n",
+ "\\frac{m_{t+1}}{p_t} - \\frac{m_{t}}{p_{t-1}} \\frac{p_{t-1}}{p_t} = g\n",
+ "$$\n",
+ "\n",
+ "or\n",
+ "\n",
+ "$$\n",
+ "b_t - b_{t-1} R_{t-1} = g\n",
+ "$$ (eq:up_bmotion)\n",
+ "\n",
+ "where\n",
+ "\n",
+ "* $b_t = \\frac{m_{t+1}}{p_t}$ is real balances at the end of period $t$\n",
+ "* $R_{t-1} = \\frac{p_{t-1}}{p_t}$ is the gross rate of return on real balances held from $t-1$ to $t$\n",
+ "\n",
+ "The demand for real balances is \n",
+ "\n",
+ "$$\n",
+ "b_t = \\gamma_1 - \\gamma_2 R_t^{-1} . \n",
+ "$$ (eq:up_bdemand)\n",
+ "\n",
+ "where $\\gamma_1 > \\gamma_2 > 0$.\n",
+ "\n",
+ "## Monetary-Fiscal Policy\n",
+ "\n",
+ "To the basic model of {doc}`money_inflation`, we add inflation-indexed one-period government bonds as an additional way for the government to finance government expenditures. \n",
+ "\n",
+ "Let $\\widetilde R > 1$ be a time-invariant gross real rate of return on government one-period inflation-indexed bonds.\n",
+ "\n",
+ "With this additional source of funds, the government's budget constraint at time $t \\geq 0$ is now\n",
+ "\n",
+ "$$\n",
+ "B_t + \\frac{m_{t+1}}{p_t} = \\widetilde R B_{t-1} + \\frac{m_t}{p_t} + g\n",
+ "$$ \n",
+ "\n",
+ "\n",
+ "Just before the beginning of time $0$, the public owns $\\check m_0$ units of currency (measured in dollars)\n",
+ "and $\\widetilde R \\check B_{-1}$ units of one-period indexed bonds (measured in time $0$ goods); these two quantities are initial conditions set outside the model.\n",
+ "\n",
+ "Notice that $\\check m_0$ is a *nominal* quantity, being measured in dollars, while\n",
+ "$\\widetilde R \\check B_{-1}$ is a *real* quantity, being measured in time $0$ goods.\n",
+ "\n",
+ "\n",
+ "### Open market operations\n",
+ "\n",
+ "At time $0$, government can rearrange its portfolio of debts subject to the following constraint (on open-market operations):\n",
+ "\n",
+ "$$\n",
+ "\\widetilde R B_{-1} + \\frac{m_0}{p_0} = \\widetilde R \\check B_{-1} + \\frac{\\check m_0}{p_0}\n",
+ "$$\n",
+ "\n",
+ "or\n",
+ "\n",
+ "$$\n",
+ "B_{-1} - \\check B_{-1} = \\frac{1}{p_0 \\widetilde R} \\left( \\check m_0 - m_0 \\right) \n",
+ "$$ (eq:openmarketconstraint)\n",
+ "\n",
+ "This equation says that the government (e.g., the central bank) can *decrease* $m_0$ relative to \n",
+ "$\\check m_0$ by *increasing* $B_{-1}$ relative to $\\check B_{-1}$. \n",
+ "\n",
+ "This is a version of a standard constraint on a central bank's [**open market operations**](https://www.federalreserve.gov/monetarypolicy/openmarket.htm) in which it expands the stock of money by buying government bonds from the public. \n",
+ "\n",
+ "## An open market operation at $t=0$\n",
+ "\n",
+ "Following Sargent and Wallace {cite}`sargent1981`, we analyze consequences of a central bank policy that \n",
+ "uses an open market operation to lower the price level in the face of a persistent fiscal\n",
+ "deficit that takes the form of a positive $g$.\n",
+ "\n",
+ "Just before time $0$, the government chooses $(m_0, B_{-1})$ subject to constraint\n",
+ "{eq}`eq:openmarketconstraint`.\n",
+ "\n",
+ "For $t =0, 1, \\ldots, T-1$,\n",
+ "\n",
+ "$$\n",
+ "\\begin{aligned}\n",
+ "B_t & = \\widetilde R B_{t-1} + g \\cr\n",
+ "m_{t+1} & = m_0 \n",
+ "\\end{aligned}\n",
+ "$$\n",
+ "\n",
+ "while for $t \\geq T$,\n",
+ "\n",
+ "$$\n",
+ "\\begin{aligned}\n",
+ "B_t & = B_{T-1} \\cr\n",
+ "m_{t+1} & = m_t + p_t \\overline g\n",
+ "\\end{aligned}\n",
+ "$$\n",
+ "\n",
+ "where \n",
+ "\n",
+ "$$\n",
+ "\\overline g = \\left[(\\tilde R -1) B_{T-1} + g \\right]\n",
+ "$$ (eq:overlineg)\n",
+ "\n",
+ "We want to compute an equilibrium $\\{p_t,m_t,b_t, R_t\\}_{t=0}$ sequence under this scheme for\n",
+ "running monetary and fiscal policies.\n",
+ "\n",
+ "Here, by **fiscal policy** we mean the collection of actions that determine a sequence of net-of-interest government deficits $\\{g_t\\}_{t=0}^\\infty$ that must be financed by issuing to the public either money or interest bearing bonds.\n",
+ "\n",
+ "By **monetary policy** or **debt-management policy**, we mean the collection of actions that determine how the government divides its portfolio of debts to the public between interest-bearing parts (government bonds) and non-interest-bearing parts (money).\n",
+ "\n",
+ "By an **open market operation**, we mean a government monetary policy action in which the government\n",
+ "(or its delegate, say, a central bank) either buys government bonds from the public for newly issued money, or sells bonds to the public and withdraws the money it receives from public circulation. \n",
+ "\n",
+ "## Algorithm (basic idea)\n",
+ "\n",
+ "\n",
+ "We work backwards from $t=T$ and first compute $p_T, R_u$ associated with the low-inflation, low-inflation-tax-rate stationary equilibrium in {doc}`money_inflation_nonlinear`.\n",
+ "\n",
+ "To start our description of our algorithm, it is useful to recall that a stationary rate of return\n",
+ "on currency $\\bar R$ solves the quadratic equation\n",
+ "\n",
+ "$$\n",
+ "-\\gamma_2 + (\\gamma_1 + \\gamma_2 - \\overline g) \\bar R - \\gamma_1 \\bar R^2 = 0\n",
+ "$$ (eq:up_steadyquadratic)\n",
+ "\n",
+ "Quadratic equation {eq}`eq:up_steadyquadratic` has two roots, $R_l < R_u < 1$.\n",
+ "\n",
+ "For reasons described at the end of {doc}`money_inflation`, we select the larger root $R_u$. \n",
+ "\n",
+ "\n",
+ "Next, we compute\n",
+ "\n",
+ "$$\n",
+ "\\begin{aligned}\n",
+ "R_T & = R_u \\cr\n",
+ "b_T & = \\gamma_1 - \\gamma_2 R_u^{-1} \\cr\n",
+ "p_T & = \\frac{m_0}{\\gamma_1 - \\overline g - \\gamma_2 R_u^{-1}}\n",
+ "\\end{aligned}\n",
+ "$$ (eq:LafferTstationary)\n",
+ "\n",
+ "\n",
+ "We can compute continuation sequences $\\{R_t, b_t\\}_{t=T+1}^\\infty$ of rates of return and real balances that are associated with an equilibrium by solving equation {eq}`eq:up_bmotion` and {eq}`eq:up_bdemand` sequentially for $t \\geq 1$:\n",
+ "\n",
+ "$$\n",
+ "\\begin{aligned}\n",
+ "b_t & = b_{t-1} R_{t-1} + \\overline g \\cr\n",
+ "R_t^{-1} & = \\frac{\\gamma_1}{\\gamma_2} - \\gamma_2^{-1} b_t \\cr\n",
+ "p_t & = R_t p_{t-1} \\cr\n",
+ " m_t & = b_{t-1} p_t \n",
+ "\\end{aligned}\n",
+ "$$\n",
+ " \n",
+ "\n",
+ "## Before time $T$ \n",
+ "\n",
+ "Define \n",
+ "\n",
+ "$$\n",
+ "\\lambda \\equiv \\frac{\\gamma_2}{\\gamma_1}.\n",
+ "$$\n",
+ "\n",
+ "Our restrictions that $\\gamma_1 > \\gamma_2 > 0$ imply that $\\lambda \\in [0,1)$.\n",
+ "\n",
+ "We want to compute\n",
+ "\n",
+ "$$ \n",
+ "\\begin{aligned}\n",
+ "p_0 & = \\gamma_1^{-1} \\left[ \\sum_{j=0}^\\infty \\lambda^j m_{j} \\right] \\cr\n",
+ "& = \\gamma_1^{-1} \\left[ \\sum_{j=0}^{T-1} \\lambda^j m_{0} + \\sum_{j=T}^\\infty \\lambda^j m_{1+j} \\right]\n",
+ "\\end{aligned}\n",
+ "$$\n",
+ "\n",
+ "Thus,\n",
+ "\n",
+ "$$\n",
+ "\\begin{aligned}\n",
+ "p_0 & = \\gamma_1^{-1} m_0 \\left\\{ \\frac{1 - \\lambda^T}{1-\\lambda} + \\frac{\\lambda^T}{R_u-\\lambda} \\right\\} \\cr\n",
+ "p_1 & = \\gamma_1^{-1} m_0 \\left\\{ \\frac{1 - \\lambda^{T-1}}{1-\\lambda} + \\frac{\\lambda^{T-1}}{R_u-\\lambda} \\right\\} \\cr\n",
+ "\\quad \\vdots & \\quad \\quad \\vdots \\cr\n",
+ "p_{T-1} & = \\gamma_1^{-1} m_0 \\left\\{ \\frac{1 - \\lambda}{1-\\lambda} + \\frac{\\lambda}{R_u-\\lambda} \\right\\} \\cr\n",
+ "p_T & = \\gamma_1^{-1} m_0 \\left\\{\\frac{1}{R_u-\\lambda} \\right\\}\n",
+ "\\end{aligned}\n",
+ "$$ (eq:allts)\n",
+ "\n",
+ "We can implement the preceding formulas by iterating on\n",
+ "\n",
+ "$$\n",
+ "p_t = \\gamma_1^{-1} m_0 + \\lambda p_{t+1}, \\quad t = T-1, T-2, \\ldots, 0\n",
+ "$$\n",
+ "\n",
+ "starting from \n",
+ "\n",
+ "$$\n",
+ "p_T = \\frac{m_0}{\\gamma_1 - \\overline g - \\gamma_2 R_u^{-1}} = \\gamma_1^{-1} m_0 \\left\\{\\frac{1}{R_u-\\lambda} \\right\\}\n",
+ "$$ (eq:pTformula)\n",
+ "\n",
+ "```{prf:remark}\n",
+ ":label: equivalence\n",
+ "We can verify the equivalence of the two formulas on the right sides of {eq}`eq:pTformula` by recalling that \n",
+ "$R_u$ is a root of the quadratic equation {eq}`eq:up_steadyquadratic` that determines steady state rates of return on currency.\n",
+ "```\n",
+ " \n",
+ "## Algorithm (pseudo code)\n",
+ "\n",
+ "Now let's describe a computational algorithm in more detail in the form of a description\n",
+ "that constitutes pseudo code because it approaches a set of instructions we could provide to a \n",
+ "Python coder.\n",
+ "\n",
+ "To compute an equilibrium, we deploy the following algorithm.\n",
+ "\n",
+ "```{prf:algorithm}\n",
+ "Given *parameters* include $g, \\check m_0, \\check B_{-1}, \\widetilde R >1, T $.\n",
+ "\n",
+ "We define a mapping from $p_0$ to $\\widehat p_0$ as follows.\n",
+ "\n",
+ "* Set $m_0$ and then compute $B_{-1}$ to satisfy the constraint on time $0$ **open market operations**\n",
+ "\n",
+ "$$\n",
+ "B_{-1}- \\check B_{-1} = \\frac{\\widetilde R}{p_0} \\left( \\check m_0 - m_0 \\right)\n",
+ "$$\n",
+ "\n",
+ "* Compute $B_{T-1}$ from\n",
+ "\n",
+ "$$\n",
+ "B_{T-1} = \\widetilde R^T B_{-1} + \\left( \\frac{1 - \\widetilde R^T}{1-\\widetilde R} \\right) g\n",
+ "$$\n",
+ "\n",
+ "* Compute \n",
+ "\n",
+ "$$\n",
+ "\\overline g = g + \\left[ \\tilde R - 1\\right] B_{T-1}\n",
+ "$$\n",
+ "\n",
+ "\n",
+ "\n",
+ "* Compute $R_u, p_T$ from formulas {eq}`eq:up_steadyquadratic` and {eq}`eq:LafferTstationary` above\n",
+ "\n",
+ "* Compute a new estimate of $p_0$, call it $\\widehat p_0$, from equation {eq}`eq:allts` above\n",
+ "\n",
+ "* Note that the preceding steps define a mapping\n",
+ "\n",
+ "$$\n",
+ "\\widehat p_0 = {\\mathcal S}(p_0)\n",
+ "$$\n",
+ "\n",
+ "* We seek a fixed point of ${\\mathcal S}$, i.e., a solution of $p_0 = {\\mathcal S}(p_0)$.\n",
+ "\n",
+ "* Compute a fixed point by iterating to convergence on the relaxation algorithm\n",
+ "\n",
+ "$$\n",
+ "p_{0,j+1} = (1-\\theta) {\\mathcal S}(p_{0,j}) + \\theta p_{0,j}, \n",
+ "$$\n",
+ "\n",
+ "where $\\theta \\in [0,1)$ is a relaxation parameter.\n",
+ "```\n",
+ "\n",
+ "## Example Calculations\n",
+ "\n",
+ "We'll set parameters of the model so that the steady state after time $T$ is initially the same\n",
+ "as in {doc}`money_inflation_nonlinear`\n",
+ "\n",
+ "In particular, we set $\\gamma_1=100, \\gamma_2 =50, g=3.0$. We set $m_0 = 100$ in that lecture,\n",
+ "but now the counterpart will be $M_T$, which is endogenous. \n",
+ "\n",
+ "As for new parameters, we'll set $\\tilde R = 1.01, \\check B_{-1} = 0, \\check m_0 = 105, T = 5$.\n",
+ "\n",
+ "We'll study a \"small\" open market operation by setting $m_0 = 100$.\n",
+ "\n",
+ "These parameter settings mean that just before time $0$, the \"central bank\" sells the public bonds in exchange for $\\check m_0 - m_0 = 5$ units of currency. \n",
+ "\n",
+ "That leaves the public with less currency but more government interest-bearing bonds.\n",
+ "\n",
+ "Since the public has less currency (its supply has diminished) it is plausible to anticipate that the price level at time $0$ will be driven downward.\n",
+ "\n",
+ "But that is not the end of the story, because this **open market operation** at time $0$ has consequences for future settings of $m_{t+1}$ and the gross-of-interest government deficit $\\bar g_t$. \n",
+ "\n",
+ "\n",
+ "Let's start with some imports:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "df278809",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "from collections import namedtuple"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "67241fc1",
+ "metadata": {},
+ "source": [
+ "Now let's dive in and implement our pseudo code in Python."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3850e676",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Create a namedtuple that contains parameters\n",
+ "MoneySupplyModel = namedtuple(\"MoneySupplyModel\", \n",
+ " [\"γ1\", \"γ2\", \"g\",\n",
+ " \"R_tilde\", \"m0_check\", \"Bm1_check\",\n",
+ " \"T\"])\n",
+ "\n",
+ "def create_model(γ1=100, γ2=50, g=3.0,\n",
+ " R_tilde=1.01,\n",
+ " Bm1_check=0, m0_check=105,\n",
+ " T=5):\n",
+ " \n",
+ " return MoneySupplyModel(γ1=γ1, γ2=γ2, g=g,\n",
+ " R_tilde=R_tilde,\n",
+ " m0_check=m0_check, Bm1_check=Bm1_check,\n",
+ " T=T)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "721a42c6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "msm = create_model()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "44e63921",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def S(p0, m0, model):\n",
+ "\n",
+ " # unpack parameters\n",
+ " γ1, γ2, g = model.γ1, model.γ2, model.g\n",
+ " R_tilde = model.R_tilde\n",
+ " m0_check, Bm1_check = model.m0_check, model.Bm1_check\n",
+ " T = model.T\n",
+ "\n",
+ " # open market operation\n",
+ " Bm1 = 1 / (p0 * R_tilde) * (m0_check - m0) + Bm1_check\n",
+ "\n",
+ " # compute B_{T-1}\n",
+ " BTm1 = R_tilde ** T * Bm1 + ((1 - R_tilde ** T) / (1 - R_tilde)) * g\n",
+ "\n",
+ " # compute g bar\n",
+ " g_bar = g + (R_tilde - 1) * BTm1\n",
+ "\n",
+ " # solve the quadratic equation\n",
+ " Ru = np.roots((-γ1, γ1 + γ2 - g_bar, -γ2)).max()\n",
+ "\n",
+ " # compute p0\n",
+ " λ = γ2 / γ1\n",
+ " p0_new = (1 / γ1) * m0 * ((1 - λ ** T) / (1 - λ) + λ ** T / (Ru - λ))\n",
+ "\n",
+ " return p0_new"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "dec0b1ae",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def compute_fixed_point(m0, p0_guess, model, θ=0.5, tol=1e-6):\n",
+ "\n",
+ " p0 = p0_guess\n",
+ " error = tol + 1\n",
+ "\n",
+ " while error > tol:\n",
+ " p0_next = (1 - θ) * S(p0, m0, model) + θ * p0\n",
+ "\n",
+ " error = np.abs(p0_next - p0)\n",
+ " p0 = p0_next\n",
+ "\n",
+ " return p0"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "db24e5df",
+ "metadata": {},
+ "source": [
+ "Let's look at how price level $p_0$ in the stationary $R_u$ equilibrium depends on the initial\n",
+ "money supply $m_0$. \n",
+ "\n",
+ "Notice that the slope of $p_0$ as a function of $m_0$ is constant.\n",
+ "\n",
+ "This outcome indicates that our model verifies a quantity theory of money outcome,\n",
+ "something that Sargent and Wallace {cite}`sargent1981` purposefully built into their model to justify\n",
+ "the adjective *monetarist* in their title."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "734dca86",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m0_arr = np.arange(10, 110, 10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4c7bbeb3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.plot(m0_arr, [compute_fixed_point(m0, 1, msm) for m0 in m0_arr])\n",
+ "\n",
+ "plt.ylabel('$p_0$')\n",
+ "plt.xlabel('$m_0$')\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a7d85ec0",
+ "metadata": {},
+ "source": [
+ "Now let's write and implement code that lets us experiment with the time $0$ open market operation described earlier."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7005ee74",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def simulate(m0, model, length=15, p0_guess=1):\n",
+ "\n",
+ " # unpack parameters\n",
+ " γ1, γ2, g = model.γ1, model.γ2, model.g\n",
+ " R_tilde = model.R_tilde\n",
+ " m0_check, Bm1_check = model.m0_check, model.Bm1_check\n",
+ " T = model.T\n",
+ "\n",
+ " # (pt, mt, bt, Rt)\n",
+ " paths = np.empty((4, length))\n",
+ "\n",
+ " # open market operation\n",
+ " p0 = compute_fixed_point(m0, 1, model)\n",
+ " Bm1 = 1 / (p0 * R_tilde) * (m0_check - m0) + Bm1_check\n",
+ " BTm1 = R_tilde ** T * Bm1 + ((1 - R_tilde ** T) / (1 - R_tilde)) * g\n",
+ " g_bar = g + (R_tilde - 1) * BTm1\n",
+ " Ru = np.roots((-γ1, γ1 + γ2 - g_bar, -γ2)).max()\n",
+ "\n",
+ " λ = γ2 / γ1\n",
+ "\n",
+ " # t = 0\n",
+ " paths[0, 0] = p0\n",
+ " paths[1, 0] = m0\n",
+ "\n",
+ " # 1 <= t <= T\n",
+ " for t in range(1, T+1, 1):\n",
+ " paths[0, t] = (1 / γ1) * m0 * \\\n",
+ " ((1 - λ ** (T - t)) / (1 - λ)\n",
+ " + (λ ** (T - t) / (Ru - λ)))\n",
+ " paths[1, t] = m0\n",
+ "\n",
+ " # t > T\n",
+ " for t in range(T+1, length):\n",
+ " paths[0, t] = paths[0, t-1] / Ru\n",
+ " paths[1, t] = paths[1, t-1] + paths[0, t] * g_bar\n",
+ "\n",
+ " # Rt = pt / pt+1\n",
+ " paths[3, :T] = paths[0, :T] / paths[0, 1:T+1]\n",
+ " paths[3, T:] = Ru\n",
+ "\n",
+ " # bt = γ1 - γ2 / Rt\n",
+ " paths[2, :] = γ1 - γ2 / paths[3, :]\n",
+ "\n",
+ " return paths"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "03ea0768",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plot_path(m0_arr, model, length=15):\n",
+ "\n",
+ " fig, axs = plt.subplots(2, 2, figsize=(8, 5))\n",
+ " titles = ['$p_t$', '$m_t$', '$b_t$', '$R_t$']\n",
+ " \n",
+ " for m0 in m0_arr:\n",
+ " paths = simulate(m0, model, length=length)\n",
+ " for i, ax in enumerate(axs.flat):\n",
+ " ax.plot(paths[i])\n",
+ " ax.set_title(titles[i])\n",
+ " \n",
+ " axs[0, 1].hlines(model.m0_check, 0, length, color='r', linestyle='--')\n",
+ " axs[0, 1].text(length * 0.8, model.m0_check * 0.9, '$\\check{m}_0$')\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2a52439d",
+ "metadata": {
+ "mystnb": {
+ "figure": {
+ "caption": "Unpleasant Arithmetic",
+ "name": "fig:unpl1"
+ }
+ }
+ },
+ "outputs": [],
+ "source": [
+ "plot_path([80, 100], msm)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "22ee3006",
+ "metadata": {},
+ "source": [
+ "{numref}`fig:unpl1` summarizes outcomes of two experiments that convey messages of Sargent and Wallace {cite}`sargent1981`.\n",
+ "\n",
+ "* An open market operation that reduces the supply of money at time $t=0$ reduces the price level at time $t=0$\n",
+ "\n",
+ "* The lower is the post-open-market-operation money supply at time $0$, lower is the price level at time $0$.\n",
+ "\n",
+ "* An open market operation that reduces the post open market operation money supply at time $0$ also *lowers* the rate of return on money $R_u$ at times $t \\geq T$ because it brings a higher gross of interest government deficit that must be financed by printing money (i.e., levying an inflation tax) at time $t \\geq T$.\n",
+ "\n",
+ "* $R$ is important in the context of maintaining monetary stability and addressing the consequences of increased inflation due to government deficits. Thus, a larger $R$ might be chosen to mitigate the negative impacts on the real rate of return caused by inflation."
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst",
+ "format_version": 0.13,
+ "jupytext_version": "1.14.1"
+ }
+ },
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "source_map": [
+ 12,
+ 326,
+ 330,
+ 334,
+ 352,
+ 356,
+ 384,
+ 397,
+ 409,
+ 413,
+ 420,
+ 424,
+ 471,
+ 488,
+ 496
+ ]
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/unpleasant.md b/book/_build/html/_sources/unpleasant.md
new file mode 100644
index 0000000..5eb80e3
--- /dev/null
+++ b/book/_build/html/_sources/unpleasant.md
@@ -0,0 +1,506 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+ format_version: 0.13
+ jupytext_version: 1.14.1
+kernelspec:
+ display_name: Python 3 (ipykernel)
+ language: python
+ name: python3
+---
+
+# Some Unpleasant Monetarist Arithmetic
+
+## Overview
+
+
+This lecture builds on concepts and issues introduced in {doc}`money_inflation`.
+
+That lecture describes stationary equilibria that reveal a [*Laffer curve*](https://en.wikipedia.org/wiki/Laffer_curve) in the inflation tax rate and the associated stationary rate of return
+on currency.
+
+In this lecture we study a situation in which a stationary equilibrium prevails after date $T > 0$, but not before then.
+
+For $t=0, \ldots, T-1$, the money supply, price level, and interest-bearing government debt vary along a transition path that ends at $t=T$.
+
+During this transition, the ratio of the real balances $\frac{m_{t+1}}{{p_t}}$ to indexed one-period government bonds $\tilde R B_{t-1}$ maturing at time $t$ decreases each period.
+
+This has consequences for the **gross-of-interest** government deficit that must be financed by printing money for times $t \geq T$.
+
+The critical **money-to-bonds** ratio stabilizes only at time $T$ and afterwards.
+
+And the larger is $T$, the higher is the gross-of-interest government deficit that must be financed
+by printing money at times $t \geq T$.
+
+These outcomes are the essential finding of Sargent and Wallace's "unpleasant monetarist arithmetic" {cite}`sargent1981`.
+
+That lecture described supplies and demands for money that appear in lecture.
+
+It also characterized the steady state equilibrium from which we work backwards in this lecture.
+
+In addition to learning about "unpleasant monetarist arithmetic", in this lecture we'll learn how to implement a [*fixed point*](https://en.wikipedia.org/wiki/Fixed_point_(mathematics)) algorithm for computing an initial price level.
+
+
+## Setup
+
+Let's start with quick reminders of the model's components set out in {doc}`money_inflation`.
+
+Please consult that lecture for more details and Python code that we'll also use in this lecture.
+
+For $t \geq 1$, **real balances** evolve according to
+
+
+$$
+\frac{m_{t+1}}{p_t} - \frac{m_{t}}{p_{t-1}} \frac{p_{t-1}}{p_t} = g
+$$
+
+or
+
+$$
+b_t - b_{t-1} R_{t-1} = g
+$$ (eq:up_bmotion)
+
+where
+
+* $b_t = \frac{m_{t+1}}{p_t}$ is real balances at the end of period $t$
+* $R_{t-1} = \frac{p_{t-1}}{p_t}$ is the gross rate of return on real balances held from $t-1$ to $t$
+
+The demand for real balances is
+
+$$
+b_t = \gamma_1 - \gamma_2 R_t^{-1} .
+$$ (eq:up_bdemand)
+
+where $\gamma_1 > \gamma_2 > 0$.
+
+## Monetary-Fiscal Policy
+
+To the basic model of {doc}`money_inflation`, we add inflation-indexed one-period government bonds as an additional way for the government to finance government expenditures.
+
+Let $\widetilde R > 1$ be a time-invariant gross real rate of return on government one-period inflation-indexed bonds.
+
+With this additional source of funds, the government's budget constraint at time $t \geq 0$ is now
+
+$$
+B_t + \frac{m_{t+1}}{p_t} = \widetilde R B_{t-1} + \frac{m_t}{p_t} + g
+$$
+
+
+Just before the beginning of time $0$, the public owns $\check m_0$ units of currency (measured in dollars)
+and $\widetilde R \check B_{-1}$ units of one-period indexed bonds (measured in time $0$ goods); these two quantities are initial conditions set outside the model.
+
+Notice that $\check m_0$ is a *nominal* quantity, being measured in dollars, while
+$\widetilde R \check B_{-1}$ is a *real* quantity, being measured in time $0$ goods.
+
+
+### Open market operations
+
+At time $0$, government can rearrange its portfolio of debts subject to the following constraint (on open-market operations):
+
+$$
+\widetilde R B_{-1} + \frac{m_0}{p_0} = \widetilde R \check B_{-1} + \frac{\check m_0}{p_0}
+$$
+
+or
+
+$$
+B_{-1} - \check B_{-1} = \frac{1}{p_0 \widetilde R} \left( \check m_0 - m_0 \right)
+$$ (eq:openmarketconstraint)
+
+This equation says that the government (e.g., the central bank) can *decrease* $m_0$ relative to
+$\check m_0$ by *increasing* $B_{-1}$ relative to $\check B_{-1}$.
+
+This is a version of a standard constraint on a central bank's [**open market operations**](https://www.federalreserve.gov/monetarypolicy/openmarket.htm) in which it expands the stock of money by buying government bonds from the public.
+
+## An open market operation at $t=0$
+
+Following Sargent and Wallace {cite}`sargent1981`, we analyze consequences of a central bank policy that
+uses an open market operation to lower the price level in the face of a persistent fiscal
+deficit that takes the form of a positive $g$.
+
+Just before time $0$, the government chooses $(m_0, B_{-1})$ subject to constraint
+{eq}`eq:openmarketconstraint`.
+
+For $t =0, 1, \ldots, T-1$,
+
+$$
+\begin{aligned}
+B_t & = \widetilde R B_{t-1} + g \cr
+m_{t+1} & = m_0
+\end{aligned}
+$$
+
+while for $t \geq T$,
+
+$$
+\begin{aligned}
+B_t & = B_{T-1} \cr
+m_{t+1} & = m_t + p_t \overline g
+\end{aligned}
+$$
+
+where
+
+$$
+\overline g = \left[(\tilde R -1) B_{T-1} + g \right]
+$$ (eq:overlineg)
+
+We want to compute an equilibrium $\{p_t,m_t,b_t, R_t\}_{t=0}$ sequence under this scheme for
+running monetary and fiscal policies.
+
+Here, by **fiscal policy** we mean the collection of actions that determine a sequence of net-of-interest government deficits $\{g_t\}_{t=0}^\infty$ that must be financed by issuing to the public either money or interest bearing bonds.
+
+By **monetary policy** or **debt-management policy**, we mean the collection of actions that determine how the government divides its portfolio of debts to the public between interest-bearing parts (government bonds) and non-interest-bearing parts (money).
+
+By an **open market operation**, we mean a government monetary policy action in which the government
+(or its delegate, say, a central bank) either buys government bonds from the public for newly issued money, or sells bonds to the public and withdraws the money it receives from public circulation.
+
+## Algorithm (basic idea)
+
+
+We work backwards from $t=T$ and first compute $p_T, R_u$ associated with the low-inflation, low-inflation-tax-rate stationary equilibrium in {doc}`money_inflation_nonlinear`.
+
+To start our description of our algorithm, it is useful to recall that a stationary rate of return
+on currency $\bar R$ solves the quadratic equation
+
+$$
+-\gamma_2 + (\gamma_1 + \gamma_2 - \overline g) \bar R - \gamma_1 \bar R^2 = 0
+$$ (eq:up_steadyquadratic)
+
+Quadratic equation {eq}`eq:up_steadyquadratic` has two roots, $R_l < R_u < 1$.
+
+For reasons described at the end of {doc}`money_inflation`, we select the larger root $R_u$.
+
+
+Next, we compute
+
+$$
+\begin{aligned}
+R_T & = R_u \cr
+b_T & = \gamma_1 - \gamma_2 R_u^{-1} \cr
+p_T & = \frac{m_0}{\gamma_1 - \overline g - \gamma_2 R_u^{-1}}
+\end{aligned}
+$$ (eq:LafferTstationary)
+
+
+We can compute continuation sequences $\{R_t, b_t\}_{t=T+1}^\infty$ of rates of return and real balances that are associated with an equilibrium by solving equation {eq}`eq:up_bmotion` and {eq}`eq:up_bdemand` sequentially for $t \geq 1$:
+
+$$
+\begin{aligned}
+b_t & = b_{t-1} R_{t-1} + \overline g \cr
+R_t^{-1} & = \frac{\gamma_1}{\gamma_2} - \gamma_2^{-1} b_t \cr
+p_t & = R_t p_{t-1} \cr
+ m_t & = b_{t-1} p_t
+\end{aligned}
+$$
+
+
+## Before time $T$
+
+Define
+
+$$
+\lambda \equiv \frac{\gamma_2}{\gamma_1}.
+$$
+
+Our restrictions that $\gamma_1 > \gamma_2 > 0$ imply that $\lambda \in [0,1)$.
+
+We want to compute
+
+$$
+\begin{aligned}
+p_0 & = \gamma_1^{-1} \left[ \sum_{j=0}^\infty \lambda^j m_{j} \right] \cr
+& = \gamma_1^{-1} \left[ \sum_{j=0}^{T-1} \lambda^j m_{0} + \sum_{j=T}^\infty \lambda^j m_{1+j} \right]
+\end{aligned}
+$$
+
+Thus,
+
+$$
+\begin{aligned}
+p_0 & = \gamma_1^{-1} m_0 \left\{ \frac{1 - \lambda^T}{1-\lambda} + \frac{\lambda^T}{R_u-\lambda} \right\} \cr
+p_1 & = \gamma_1^{-1} m_0 \left\{ \frac{1 - \lambda^{T-1}}{1-\lambda} + \frac{\lambda^{T-1}}{R_u-\lambda} \right\} \cr
+\quad \vdots & \quad \quad \vdots \cr
+p_{T-1} & = \gamma_1^{-1} m_0 \left\{ \frac{1 - \lambda}{1-\lambda} + \frac{\lambda}{R_u-\lambda} \right\} \cr
+p_T & = \gamma_1^{-1} m_0 \left\{\frac{1}{R_u-\lambda} \right\}
+\end{aligned}
+$$ (eq:allts)
+
+We can implement the preceding formulas by iterating on
+
+$$
+p_t = \gamma_1^{-1} m_0 + \lambda p_{t+1}, \quad t = T-1, T-2, \ldots, 0
+$$
+
+starting from
+
+$$
+p_T = \frac{m_0}{\gamma_1 - \overline g - \gamma_2 R_u^{-1}} = \gamma_1^{-1} m_0 \left\{\frac{1}{R_u-\lambda} \right\}
+$$ (eq:pTformula)
+
+```{prf:remark}
+:label: equivalence
+We can verify the equivalence of the two formulas on the right sides of {eq}`eq:pTformula` by recalling that
+$R_u$ is a root of the quadratic equation {eq}`eq:up_steadyquadratic` that determines steady state rates of return on currency.
+```
+
+## Algorithm (pseudo code)
+
+Now let's describe a computational algorithm in more detail in the form of a description
+that constitutes pseudo code because it approaches a set of instructions we could provide to a
+Python coder.
+
+To compute an equilibrium, we deploy the following algorithm.
+
+```{prf:algorithm}
+Given *parameters* include $g, \check m_0, \check B_{-1}, \widetilde R >1, T $.
+
+We define a mapping from $p_0$ to $\widehat p_0$ as follows.
+
+* Set $m_0$ and then compute $B_{-1}$ to satisfy the constraint on time $0$ **open market operations**
+
+$$
+B_{-1}- \check B_{-1} = \frac{\widetilde R}{p_0} \left( \check m_0 - m_0 \right)
+$$
+
+* Compute $B_{T-1}$ from
+
+$$
+B_{T-1} = \widetilde R^T B_{-1} + \left( \frac{1 - \widetilde R^T}{1-\widetilde R} \right) g
+$$
+
+* Compute
+
+$$
+\overline g = g + \left[ \tilde R - 1\right] B_{T-1}
+$$
+
+
+
+* Compute $R_u, p_T$ from formulas {eq}`eq:up_steadyquadratic` and {eq}`eq:LafferTstationary` above
+
+* Compute a new estimate of $p_0$, call it $\widehat p_0$, from equation {eq}`eq:allts` above
+
+* Note that the preceding steps define a mapping
+
+$$
+\widehat p_0 = {\mathcal S}(p_0)
+$$
+
+* We seek a fixed point of ${\mathcal S}$, i.e., a solution of $p_0 = {\mathcal S}(p_0)$.
+
+* Compute a fixed point by iterating to convergence on the relaxation algorithm
+
+$$
+p_{0,j+1} = (1-\theta) {\mathcal S}(p_{0,j}) + \theta p_{0,j},
+$$
+
+where $\theta \in [0,1)$ is a relaxation parameter.
+```
+
+## Example Calculations
+
+We'll set parameters of the model so that the steady state after time $T$ is initially the same
+as in {doc}`money_inflation_nonlinear`
+
+In particular, we set $\gamma_1=100, \gamma_2 =50, g=3.0$. We set $m_0 = 100$ in that lecture,
+but now the counterpart will be $M_T$, which is endogenous.
+
+As for new parameters, we'll set $\tilde R = 1.01, \check B_{-1} = 0, \check m_0 = 105, T = 5$.
+
+We'll study a "small" open market operation by setting $m_0 = 100$.
+
+These parameter settings mean that just before time $0$, the "central bank" sells the public bonds in exchange for $\check m_0 - m_0 = 5$ units of currency.
+
+That leaves the public with less currency but more government interest-bearing bonds.
+
+Since the public has less currency (its supply has diminished) it is plausible to anticipate that the price level at time $0$ will be driven downward.
+
+But that is not the end of the story, because this **open market operation** at time $0$ has consequences for future settings of $m_{t+1}$ and the gross-of-interest government deficit $\bar g_t$.
+
+
+Let's start with some imports:
+
+```{code-cell} ipython3
+import numpy as np
+import matplotlib.pyplot as plt
+from collections import namedtuple
+```
+
+Now let's dive in and implement our pseudo code in Python.
+
+```{code-cell} ipython3
+# Create a namedtuple that contains parameters
+MoneySupplyModel = namedtuple("MoneySupplyModel",
+ ["γ1", "γ2", "g",
+ "R_tilde", "m0_check", "Bm1_check",
+ "T"])
+
+def create_model(γ1=100, γ2=50, g=3.0,
+ R_tilde=1.01,
+ Bm1_check=0, m0_check=105,
+ T=5):
+
+ return MoneySupplyModel(γ1=γ1, γ2=γ2, g=g,
+ R_tilde=R_tilde,
+ m0_check=m0_check, Bm1_check=Bm1_check,
+ T=T)
+```
+
+```{code-cell} ipython3
+msm = create_model()
+```
+
+```{code-cell} ipython3
+def S(p0, m0, model):
+
+ # unpack parameters
+ γ1, γ2, g = model.γ1, model.γ2, model.g
+ R_tilde = model.R_tilde
+ m0_check, Bm1_check = model.m0_check, model.Bm1_check
+ T = model.T
+
+ # open market operation
+ Bm1 = 1 / (p0 * R_tilde) * (m0_check - m0) + Bm1_check
+
+ # compute B_{T-1}
+ BTm1 = R_tilde ** T * Bm1 + ((1 - R_tilde ** T) / (1 - R_tilde)) * g
+
+ # compute g bar
+ g_bar = g + (R_tilde - 1) * BTm1
+
+ # solve the quadratic equation
+ Ru = np.roots((-γ1, γ1 + γ2 - g_bar, -γ2)).max()
+
+ # compute p0
+ λ = γ2 / γ1
+ p0_new = (1 / γ1) * m0 * ((1 - λ ** T) / (1 - λ) + λ ** T / (Ru - λ))
+
+ return p0_new
+```
+
+```{code-cell} ipython3
+def compute_fixed_point(m0, p0_guess, model, θ=0.5, tol=1e-6):
+
+ p0 = p0_guess
+ error = tol + 1
+
+ while error > tol:
+ p0_next = (1 - θ) * S(p0, m0, model) + θ * p0
+
+ error = np.abs(p0_next - p0)
+ p0 = p0_next
+
+ return p0
+```
+
+Let's look at how price level $p_0$ in the stationary $R_u$ equilibrium depends on the initial
+money supply $m_0$.
+
+Notice that the slope of $p_0$ as a function of $m_0$ is constant.
+
+This outcome indicates that our model verifies a quantity theory of money outcome,
+something that Sargent and Wallace {cite}`sargent1981` purposefully built into their model to justify
+the adjective *monetarist* in their title.
+
+
+```{code-cell} ipython3
+m0_arr = np.arange(10, 110, 10)
+```
+
+```{code-cell} ipython3
+plt.plot(m0_arr, [compute_fixed_point(m0, 1, msm) for m0 in m0_arr])
+
+plt.ylabel('$p_0$')
+plt.xlabel('$m_0$')
+
+plt.show()
+```
+
+Now let's write and implement code that lets us experiment with the time $0$ open market operation described earlier.
+
+```{code-cell} ipython3
+def simulate(m0, model, length=15, p0_guess=1):
+
+ # unpack parameters
+ γ1, γ2, g = model.γ1, model.γ2, model.g
+ R_tilde = model.R_tilde
+ m0_check, Bm1_check = model.m0_check, model.Bm1_check
+ T = model.T
+
+ # (pt, mt, bt, Rt)
+ paths = np.empty((4, length))
+
+ # open market operation
+ p0 = compute_fixed_point(m0, 1, model)
+ Bm1 = 1 / (p0 * R_tilde) * (m0_check - m0) + Bm1_check
+ BTm1 = R_tilde ** T * Bm1 + ((1 - R_tilde ** T) / (1 - R_tilde)) * g
+ g_bar = g + (R_tilde - 1) * BTm1
+ Ru = np.roots((-γ1, γ1 + γ2 - g_bar, -γ2)).max()
+
+ λ = γ2 / γ1
+
+ # t = 0
+ paths[0, 0] = p0
+ paths[1, 0] = m0
+
+ # 1 <= t <= T
+ for t in range(1, T+1, 1):
+ paths[0, t] = (1 / γ1) * m0 * \
+ ((1 - λ ** (T - t)) / (1 - λ)
+ + (λ ** (T - t) / (Ru - λ)))
+ paths[1, t] = m0
+
+ # t > T
+ for t in range(T+1, length):
+ paths[0, t] = paths[0, t-1] / Ru
+ paths[1, t] = paths[1, t-1] + paths[0, t] * g_bar
+
+ # Rt = pt / pt+1
+ paths[3, :T] = paths[0, :T] / paths[0, 1:T+1]
+ paths[3, T:] = Ru
+
+ # bt = γ1 - γ2 / Rt
+ paths[2, :] = γ1 - γ2 / paths[3, :]
+
+ return paths
+```
+
+```{code-cell} ipython3
+def plot_path(m0_arr, model, length=15):
+
+ fig, axs = plt.subplots(2, 2, figsize=(8, 5))
+ titles = ['$p_t$', '$m_t$', '$b_t$', '$R_t$']
+
+ for m0 in m0_arr:
+ paths = simulate(m0, model, length=length)
+ for i, ax in enumerate(axs.flat):
+ ax.plot(paths[i])
+ ax.set_title(titles[i])
+
+ axs[0, 1].hlines(model.m0_check, 0, length, color='r', linestyle='--')
+ axs[0, 1].text(length * 0.8, model.m0_check * 0.9, '$\check{m}_0$')
+ plt.show()
+```
+
+```{code-cell} ipython3
+---
+mystnb:
+ figure:
+ caption: "Unpleasant Arithmetic"
+ name: fig:unpl1
+---
+plot_path([80, 100], msm)
+```
+
+{numref}`fig:unpl1` summarizes outcomes of two experiments that convey messages of Sargent and Wallace {cite}`sargent1981`.
+
+* An open market operation that reduces the supply of money at time $t=0$ reduces the price level at time $t=0$
+
+* The lower is the post-open-market-operation money supply at time $0$, lower is the price level at time $0$.
+
+* An open market operation that reduces the post open market operation money supply at time $0$ also *lowers* the rate of return on money $R_u$ at times $t \geq T$ because it brings a higher gross of interest government deficit that must be financed by printing money (i.e., levying an inflation tax) at time $t \geq T$.
+
+* $R$ is important in the context of maintaining monetary stability and addressing the consequences of increased inflation due to government deficits. Thus, a larger $R$ might be chosen to mitigate the negative impacts on the real rate of return caused by inflation.
diff --git a/content/lectures/zreferences.ipynb b/book/_build/html/_sources/zreferences.ipynb
similarity index 69%
rename from content/lectures/zreferences.ipynb
rename to book/_build/html/_sources/zreferences.ipynb
index 477fa94..c6210a9 100644
--- a/content/lectures/zreferences.ipynb
+++ b/book/_build/html/_sources/zreferences.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "d191fa4c",
+ "id": "f1cfe933",
"metadata": {},
"source": [
"(references)=\n",
@@ -14,12 +14,21 @@
}
],
"metadata": {
+ "jupytext": {
+ "text_representation": {
+ "extension": ".md",
+ "format_name": "myst"
+ }
+ },
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
- }
+ },
+ "source_map": [
+ 10
+ ]
},
"nbformat": 4,
"nbformat_minor": 5
-}
+}
\ No newline at end of file
diff --git a/book/_build/html/_sources/zreferences.md b/book/_build/html/_sources/zreferences.md
new file mode 100644
index 0000000..5f17e89
--- /dev/null
+++ b/book/_build/html/_sources/zreferences.md
@@ -0,0 +1,17 @@
+---
+jupytext:
+ text_representation:
+ extension: .md
+ format_name: myst
+kernelspec:
+ display_name: Python 3
+ language: python
+ name: python3
+---
+
+(references)=
+# References
+
+```{bibliography} _static/quant-econ.bib
+```
+
diff --git a/book/_build/html/_sphinx_design_static/design-tabs.js b/book/_build/html/_sphinx_design_static/design-tabs.js
new file mode 100644
index 0000000..b25bd6a
--- /dev/null
+++ b/book/_build/html/_sphinx_design_static/design-tabs.js
@@ -0,0 +1,101 @@
+// @ts-check
+
+// Extra JS capability for selected tabs to be synced
+// The selection is stored in local storage so that it persists across page loads.
+
+/**
+ * @type {Record}
+ */
+let sd_id_to_elements = {};
+const storageKeyPrefix = "sphinx-design-tab-id-";
+
+/**
+ * Create a key for a tab element.
+ * @param {HTMLElement} el - The tab element.
+ * @returns {[string, string, string] | null} - The key.
+ *
+ */
+function create_key(el) {
+ let syncId = el.getAttribute("data-sync-id");
+ let syncGroup = el.getAttribute("data-sync-group");
+ if (!syncId || !syncGroup) return null;
+ return [syncGroup, syncId, syncGroup + "--" + syncId];
+}
+
+/**
+ * Initialize the tab selection.
+ *
+ */
+function ready() {
+ // Find all tabs with sync data
+
+ /** @type {string[]} */
+ let groups = [];
+
+ document.querySelectorAll(".sd-tab-label").forEach((label) => {
+ if (label instanceof HTMLElement) {
+ let data = create_key(label);
+ if (data) {
+ let [group, id, key] = data;
+
+ // add click event listener
+ // @ts-ignore
+ label.onclick = onSDLabelClick;
+
+ // store map of key to elements
+ if (!sd_id_to_elements[key]) {
+ sd_id_to_elements[key] = [];
+ }
+ sd_id_to_elements[key].push(label);
+
+ if (groups.indexOf(group) === -1) {
+ groups.push(group);
+ // Check if a specific tab has been selected via URL parameter
+ const tabParam = new URLSearchParams(window.location.search).get(
+ group
+ );
+ if (tabParam) {
+ console.log(
+ "sphinx-design: Selecting tab id for group '" +
+ group +
+ "' from URL parameter: " +
+ tabParam
+ );
+ window.sessionStorage.setItem(storageKeyPrefix + group, tabParam);
+ }
+ }
+
+ // Check is a specific tab has been selected previously
+ let previousId = window.sessionStorage.getItem(
+ storageKeyPrefix + group
+ );
+ if (previousId === id) {
+ // console.log(
+ // "sphinx-design: Selecting tab from session storage: " + id
+ // );
+ // @ts-ignore
+ label.previousElementSibling.checked = true;
+ }
+ }
+ }
+ });
+}
+
+/**
+ * Activate other tabs with the same sync id.
+ *
+ * @this {HTMLElement} - The element that was clicked.
+ */
+function onSDLabelClick() {
+ let data = create_key(this);
+ if (!data) return;
+ let [group, id, key] = data;
+ for (const label of sd_id_to_elements[key]) {
+ if (label === this) continue;
+ // @ts-ignore
+ label.previousElementSibling.checked = true;
+ }
+ window.sessionStorage.setItem(storageKeyPrefix + group, id);
+}
+
+document.addEventListener("DOMContentLoaded", ready, false);
diff --git a/book/_build/html/_sphinx_design_static/sphinx-design.5ea377869091fd0449014c60fc090103.min.css b/book/_build/html/_sphinx_design_static/sphinx-design.5ea377869091fd0449014c60fc090103.min.css
new file mode 100644
index 0000000..a325746
--- /dev/null
+++ b/book/_build/html/_sphinx_design_static/sphinx-design.5ea377869091fd0449014c60fc090103.min.css
@@ -0,0 +1 @@
+.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative;font-size:var(--sd-fontsize-dropdown)}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary.sd-summary-title{padding:.5em 1em;font-size:var(--sd-fontsize-dropdown-title);font-weight:var(--sd-fontweight-dropdown-title);user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;list-style:none;display:inline-flex;justify-content:space-between}details.sd-dropdown summary.sd-summary-title::-webkit-details-marker{display:none}details.sd-dropdown summary.sd-summary-title:focus{outline:none}details.sd-dropdown summary.sd-summary-title .sd-summary-icon{margin-right:.6em;display:inline-flex;align-items:center}details.sd-dropdown summary.sd-summary-title .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary.sd-summary-title .sd-summary-text{flex-grow:1;line-height:1.5;padding-right:.5rem}details.sd-dropdown summary.sd-summary-title .sd-summary-state-marker{pointer-events:none;display:inline-flex;align-items:center}details.sd-dropdown summary.sd-summary-title .sd-summary-state-marker svg{opacity:.6}details.sd-dropdown summary.sd-summary-title:hover .sd-summary-state-marker svg{opacity:1;transform:scale(1.1)}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown .sd-summary-chevron-right{transition:.25s}details.sd-dropdown[open]>.sd-summary-title .sd-summary-chevron-right{transform:rotate(90deg)}details.sd-dropdown[open]>.sd-summary-title .sd-summary-chevron-down{transform:rotate(180deg)}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-bg: rgba(0, 113, 188, 0.2);--sd-color-secondary-bg: rgba(108, 117, 125, 0.2);--sd-color-success-bg: rgba(40, 167, 69, 0.2);--sd-color-info-bg: rgba(23, 162, 184, 0.2);--sd-color-warning-bg: rgba(240, 179, 126, 0.2);--sd-color-danger-bg: rgba(220, 53, 69, 0.2);--sd-color-light-bg: rgba(248, 249, 250, 0.2);--sd-color-muted-bg: rgba(108, 117, 125, 0.2);--sd-color-dark-bg: rgba(33, 37, 41, 0.2);--sd-color-black-bg: rgba(0, 0, 0, 0.2);--sd-color-white-bg: rgba(255, 255, 255, 0.2);--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem;--sd-fontsize-dropdown: inherit;--sd-fontsize-dropdown-title: 1rem;--sd-fontweight-dropdown-title: 700}
diff --git a/book/_build/html/_static/1078.index.js b/book/_build/html/_static/1078.index.js
new file mode 100644
index 0000000..c33dfba
--- /dev/null
+++ b/book/_build/html/_static/1078.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[1078],{41078:(e,t,n)=>{function r(e,t,n){return void 0===n&&(n=""),void 0===t&&(t="\\b"),new RegExp("^"+n+"(("+e.join(")|(")+"))"+t)}n.r(t),n.d(t,{julia:()=>_});var a=["[<>]:","[<>=]=","<<=?",">>>?=?","=>","--?>","<--[->]?","\\/\\/","\\.{2,3}","[\\.\\\\%*+\\-<>!\\/^|&]=?","\\?","\\$","~",":"],i=r(["[<>]:","[<>=]=","[!=]==","<<=?",">>>?=?","=>?","--?>","<--[->]?","\\/\\/","[\\\\%*+\\-<>!\\/^|&\\u00F7\\u22BB]=?","\\?","\\$","~",":","\\u00D7","\\u2208","\\u2209","\\u220B","\\u220C","\\u2218","\\u221A","\\u221B","\\u2229","\\u222A","\\u2260","\\u2264","\\u2265","\\u2286","\\u2288","\\u228A","\\u22C5","\\b(in|isa)\\b(?!.?\\()"],""),s=/^[;,()[\]{}]/,u=/^[_A-Za-z\u00A1-\u2217\u2219-\uFFFF][\w\u00A1-\u2217\u2219-\uFFFF]*!*/,o=r(["\\\\[0-7]{1,3}","\\\\x[A-Fa-f0-9]{1,2}","\\\\[abefnrtv0%?'\"\\\\]","([^\\u0027\\u005C\\uD800-\\uDFFF]|[\\uD800-\\uDFFF][\\uDC00-\\uDFFF])"],"'"),c=["if","else","elseif","while","for","begin","let","end","do","try","catch","finally","return","break","continue","global","local","const","export","import","importall","using","function","where","macro","module","baremodule","struct","type","mutable","immutable","quote","typealias","abstract","primitive","bitstype"],l=["true","false","nothing","NaN","Inf"],m=r(["begin","function","type","struct","immutable","let","macro","for","while","quote","if","else","elseif","try","finally","catch","do"]),f=r(["end","else","elseif","catch","finally"]),p=r(c),h=r(l),d=/^@[_A-Za-z\u00A1-\uFFFF][\w\u00A1-\uFFFF]*!*/,F=/^:[_A-Za-z\u00A1-\uFFFF][\w\u00A1-\uFFFF]*!*/,k=/^(`|([_A-Za-z\u00A1-\uFFFF]*"("")?))/,b=r(a,"","@"),g=r(a,"",":");function v(e){return e.nestedArrays>0}function x(e,t){return void 0===t&&(t=0),e.scopes.length<=t?null:e.scopes[e.scopes.length-(t+1)]}function A(e,t){if(e.match("#=",!1))return t.tokenize=y,t.tokenize(e,t);var n=t.leavingExpr;if(e.sol()&&(n=!1),t.leavingExpr=!1,n&&e.match(/^'+/))return"operator";if(e.match(/\.{4,}/))return"error";if(e.match(/\.{1,3}/))return"operator";if(e.eatSpace())return null;var r,a,o=e.peek();if("#"===o)return e.skipToEnd(),"comment";if("["===o&&(t.scopes.push("["),t.nestedArrays++),"("===o&&(t.scopes.push("("),t.nestedGenerators++),v(t)&&"]"===o){for(;t.scopes.length&&"["!==x(t);)t.scopes.pop();t.scopes.pop(),t.nestedArrays--,t.leavingExpr=!0}if(function(e){return e.nestedGenerators>0}(t)&&")"===o){for(;t.scopes.length&&"("!==x(t);)t.scopes.pop();t.scopes.pop(),t.nestedGenerators--,t.leavingExpr=!0}if(v(t)){if("end"==t.lastToken&&e.match(":"))return"operator";if(e.match("end"))return"number"}if((r=e.match(m,!1))&&t.scopes.push(r[0]),e.match(f,!1)&&t.scopes.pop(),e.match(/^::(?![:\$])/))return t.tokenize=z,t.tokenize(e,t);if(!n&&(e.match(F)||e.match(g)))return"builtin";if(e.match(i))return"operator";if(e.match(/^\.?\d/,!1)){var c=RegExp(/^im\b/),l=!1;if(e.match(/^0x\.[0-9a-f_]+p[\+\-]?[_\d]+/i)&&(l=!0),e.match(/^0x[0-9a-f_]+/i)&&(l=!0),e.match(/^0b[01_]+/i)&&(l=!0),e.match(/^0o[0-7_]+/i)&&(l=!0),e.match(/^(?:(?:\d[_\d]*)?\.(?!\.)(?:\d[_\d]*)?|\d[_\d]*\.(?!\.)(?:\d[_\d]*))?([Eef][\+\-]?[_\d]+)?/i)&&(l=!0),e.match(/^\d[_\d]*(e[\+\-]?\d+)?/i)&&(l=!0),l)return e.match(c),t.leavingExpr=!0,"number"}if(e.match("'"))return t.tokenize=E,t.tokenize(e,t);if(e.match(k))return t.tokenize=('"""'===(a=e.current()).substr(-3)?a='"""':'"'===a.substr(-1)&&(a='"'),function(e,t){if(e.eat("\\"))e.next();else{if(e.match(a))return t.tokenize=A,t.leavingExpr=!0,"string";e.eat(/[`"]/)}return e.eatWhile(/[^\\`"]/),"string"}),t.tokenize(e,t);if(e.match(d)||e.match(b))return"meta";if(e.match(s))return null;if(e.match(p))return"keyword";if(e.match(h))return"builtin";var _=t.isDefinition||"function"==t.lastToken||"macro"==t.lastToken||"type"==t.lastToken||"struct"==t.lastToken||"immutable"==t.lastToken;return e.match(u)?_?"."===e.peek()?(t.isDefinition=!0,"variable"):(t.isDefinition=!1,"def"):(t.leavingExpr=!0,"variable"):(e.next(),"error")}function z(e,t){return e.match(/.*?(?=[,;{}()=\s]|$)/),e.match("{")?t.nestedParameters++:e.match("}")&&t.nestedParameters>0&&t.nestedParameters--,t.nestedParameters>0?e.match(/.*?(?={|})/)||e.next():0==t.nestedParameters&&(t.tokenize=A),"builtin"}function y(e,t){return e.match("#=")&&t.nestedComments++,e.match(/.*?(?=(#=|=#))/)||e.skipToEnd(),e.match("=#")&&(t.nestedComments--,0==t.nestedComments&&(t.tokenize=A)),"comment"}function E(e,t){var n,r=!1;if(e.match(o))r=!0;else if(n=e.match(/\\u([a-f0-9]{1,4})(?=')/i))((a=parseInt(n[1],16))<=55295||a>=57344)&&(r=!0,e.next());else if(n=e.match(/\\U([A-Fa-f0-9]{5,8})(?=')/)){var a;(a=parseInt(n[1],16))<=1114111&&(r=!0,e.next())}return r?(t.leavingExpr=!0,t.tokenize=A,"string"):(e.match(/^[^']+(?=')/)||e.skipToEnd(),e.match("'")&&(t.tokenize=A),"error")}const _={name:"julia",startState:function(){return{tokenize:A,scopes:[],lastToken:null,leavingExpr:!1,isDefinition:!1,nestedArrays:0,nestedComments:0,nestedGenerators:0,nestedParameters:0,firstParenPos:-1}},token:function(e,t){var n=t.tokenize(e,t),r=e.current();return r&&n&&(t.lastToken=r),n},indent:function(e,t,n){var r=0;return("]"===t||")"===t||/^end\b/.test(t)||/^else/.test(t)||/^catch\b/.test(t)||/^elseif\b/.test(t)||/^finally/.test(t))&&(r=-1),(e.scopes.length+r)*n.unit},languageData:{indentOnInput:/^\s*(end|else|catch|finally)\b$/,commentTokens:{line:"#",block:{open:"#=",close:"=#"}},closeBrackets:{brackets:["(","[","{",'"']},autocomplete:c.concat(l)}}}}]);
+//# sourceMappingURL=1078.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/1078.index.js.map b/book/_build/html/_static/1078.index.js.map
new file mode 100644
index 0000000..1adf466
--- /dev/null
+++ b/book/_build/html/_static/1078.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"1078.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/julia.js"],"sourcesContent":["function wordRegexp(words, end, pre) {\n if (typeof pre === \"undefined\") pre = \"\";\n if (typeof end === \"undefined\") { end = \"\\\\b\"; }\n return new RegExp(\"^\" + pre + \"((\" + words.join(\")|(\") + \"))\" + end);\n}\n\nvar octChar = \"\\\\\\\\[0-7]{1,3}\";\nvar hexChar = \"\\\\\\\\x[A-Fa-f0-9]{1,2}\";\nvar sChar = \"\\\\\\\\[abefnrtv0%?'\\\"\\\\\\\\]\";\nvar uChar = \"([^\\\\u0027\\\\u005C\\\\uD800-\\\\uDFFF]|[\\\\uD800-\\\\uDFFF][\\\\uDC00-\\\\uDFFF])\";\n\nvar asciiOperatorsList = [\n \"[<>]:\", \"[<>=]=\", \"<<=?\", \">>>?=?\", \"=>\", \"--?>\", \"<--[->]?\", \"\\\\/\\\\/\",\n \"\\\\.{2,3}\", \"[\\\\.\\\\\\\\%*+\\\\-<>!\\\\/^|&]=?\", \"\\\\?\", \"\\\\$\", \"~\", \":\"\n];\nvar operators = wordRegexp([\n \"[<>]:\", \"[<>=]=\", \"[!=]==\", \"<<=?\", \">>>?=?\", \"=>?\", \"--?>\", \"<--[->]?\", \"\\\\/\\\\/\",\n \"[\\\\\\\\%*+\\\\-<>!\\\\/^|&\\\\u00F7\\\\u22BB]=?\", \"\\\\?\", \"\\\\$\", \"~\", \":\",\n \"\\\\u00D7\", \"\\\\u2208\", \"\\\\u2209\", \"\\\\u220B\", \"\\\\u220C\", \"\\\\u2218\",\n \"\\\\u221A\", \"\\\\u221B\", \"\\\\u2229\", \"\\\\u222A\", \"\\\\u2260\", \"\\\\u2264\",\n \"\\\\u2265\", \"\\\\u2286\", \"\\\\u2288\", \"\\\\u228A\", \"\\\\u22C5\",\n \"\\\\b(in|isa)\\\\b(?!\\.?\\\\()\"\n], \"\");\nvar delimiters = /^[;,()[\\]{}]/;\nvar identifiers = /^[_A-Za-z\\u00A1-\\u2217\\u2219-\\uFFFF][\\w\\u00A1-\\u2217\\u2219-\\uFFFF]*!*/;\n\nvar chars = wordRegexp([octChar, hexChar, sChar, uChar], \"'\");\n\nvar openersList = [\"begin\", \"function\", \"type\", \"struct\", \"immutable\", \"let\",\n \"macro\", \"for\", \"while\", \"quote\", \"if\", \"else\", \"elseif\", \"try\",\n \"finally\", \"catch\", \"do\"];\n\nvar closersList = [\"end\", \"else\", \"elseif\", \"catch\", \"finally\"];\n\nvar keywordsList = [\"if\", \"else\", \"elseif\", \"while\", \"for\", \"begin\", \"let\",\n \"end\", \"do\", \"try\", \"catch\", \"finally\", \"return\", \"break\", \"continue\",\n \"global\", \"local\", \"const\", \"export\", \"import\", \"importall\", \"using\",\n \"function\", \"where\", \"macro\", \"module\", \"baremodule\", \"struct\", \"type\",\n \"mutable\", \"immutable\", \"quote\", \"typealias\", \"abstract\", \"primitive\",\n \"bitstype\"];\n\nvar builtinsList = [\"true\", \"false\", \"nothing\", \"NaN\", \"Inf\"];\n\nvar openers = wordRegexp(openersList);\nvar closers = wordRegexp(closersList);\nvar keywords = wordRegexp(keywordsList);\nvar builtins = wordRegexp(builtinsList);\n\nvar macro = /^@[_A-Za-z\\u00A1-\\uFFFF][\\w\\u00A1-\\uFFFF]*!*/;\nvar symbol = /^:[_A-Za-z\\u00A1-\\uFFFF][\\w\\u00A1-\\uFFFF]*!*/;\nvar stringPrefixes = /^(`|([_A-Za-z\\u00A1-\\uFFFF]*\"(\"\")?))/;\n\nvar macroOperators = wordRegexp(asciiOperatorsList, \"\", \"@\");\nvar symbolOperators = wordRegexp(asciiOperatorsList, \"\", \":\");\n\nfunction inArray(state) {\n return (state.nestedArrays > 0);\n}\n\nfunction inGenerator(state) {\n return (state.nestedGenerators > 0);\n}\n\nfunction currentScope(state, n) {\n if (typeof(n) === \"undefined\") { n = 0; }\n if (state.scopes.length <= n) {\n return null;\n }\n return state.scopes[state.scopes.length - (n + 1)];\n}\n\n// tokenizers\nfunction tokenBase(stream, state) {\n // Handle multiline comments\n if (stream.match('#=', false)) {\n state.tokenize = tokenComment;\n return state.tokenize(stream, state);\n }\n\n // Handle scope changes\n var leavingExpr = state.leavingExpr;\n if (stream.sol()) {\n leavingExpr = false;\n }\n state.leavingExpr = false;\n\n if (leavingExpr) {\n if (stream.match(/^'+/)) {\n return \"operator\";\n }\n }\n\n if (stream.match(/\\.{4,}/)) {\n return \"error\";\n } else if (stream.match(/\\.{1,3}/)) {\n return \"operator\";\n }\n\n if (stream.eatSpace()) {\n return null;\n }\n\n var ch = stream.peek();\n\n // Handle single line comments\n if (ch === '#') {\n stream.skipToEnd();\n return \"comment\";\n }\n\n if (ch === '[') {\n state.scopes.push('[');\n state.nestedArrays++;\n }\n\n if (ch === '(') {\n state.scopes.push('(');\n state.nestedGenerators++;\n }\n\n if (inArray(state) && ch === ']') {\n while (state.scopes.length && currentScope(state) !== \"[\") { state.scopes.pop(); }\n state.scopes.pop();\n state.nestedArrays--;\n state.leavingExpr = true;\n }\n\n if (inGenerator(state) && ch === ')') {\n while (state.scopes.length && currentScope(state) !== \"(\") { state.scopes.pop(); }\n state.scopes.pop();\n state.nestedGenerators--;\n state.leavingExpr = true;\n }\n\n if (inArray(state)) {\n if (state.lastToken == \"end\" && stream.match(':')) {\n return \"operator\";\n }\n if (stream.match('end')) {\n return \"number\";\n }\n }\n\n var match;\n if (match = stream.match(openers, false)) {\n state.scopes.push(match[0]);\n }\n\n if (stream.match(closers, false)) {\n state.scopes.pop();\n }\n\n // Handle type annotations\n if (stream.match(/^::(?![:\\$])/)) {\n state.tokenize = tokenAnnotation;\n return state.tokenize(stream, state);\n }\n\n // Handle symbols\n if (!leavingExpr && (stream.match(symbol) || stream.match(symbolOperators))) {\n return \"builtin\";\n }\n\n // Handle parametric types\n //if (stream.match(/^{[^}]*}(?=\\()/)) {\n // return \"builtin\";\n //}\n\n // Handle operators and Delimiters\n if (stream.match(operators)) {\n return \"operator\";\n }\n\n // Handle Number Literals\n if (stream.match(/^\\.?\\d/, false)) {\n var imMatcher = RegExp(/^im\\b/);\n var numberLiteral = false;\n if (stream.match(/^0x\\.[0-9a-f_]+p[\\+\\-]?[_\\d]+/i)) { numberLiteral = true; }\n // Integers\n if (stream.match(/^0x[0-9a-f_]+/i)) { numberLiteral = true; } // Hex\n if (stream.match(/^0b[01_]+/i)) { numberLiteral = true; } // Binary\n if (stream.match(/^0o[0-7_]+/i)) { numberLiteral = true; } // Octal\n // Floats\n if (stream.match(/^(?:(?:\\d[_\\d]*)?\\.(?!\\.)(?:\\d[_\\d]*)?|\\d[_\\d]*\\.(?!\\.)(?:\\d[_\\d]*))?([Eef][\\+\\-]?[_\\d]+)?/i)) { numberLiteral = true; }\n if (stream.match(/^\\d[_\\d]*(e[\\+\\-]?\\d+)?/i)) { numberLiteral = true; } // Decimal\n if (numberLiteral) {\n // Integer literals may be \"long\"\n stream.match(imMatcher);\n state.leavingExpr = true;\n return \"number\";\n }\n }\n\n // Handle Chars\n if (stream.match(\"'\")) {\n state.tokenize = tokenChar;\n return state.tokenize(stream, state);\n }\n\n // Handle Strings\n if (stream.match(stringPrefixes)) {\n state.tokenize = tokenStringFactory(stream.current());\n return state.tokenize(stream, state);\n }\n\n if (stream.match(macro) || stream.match(macroOperators)) {\n return \"meta\";\n }\n\n if (stream.match(delimiters)) {\n return null;\n }\n\n if (stream.match(keywords)) {\n return \"keyword\";\n }\n\n if (stream.match(builtins)) {\n return \"builtin\";\n }\n\n var isDefinition = state.isDefinition || state.lastToken == \"function\" ||\n state.lastToken == \"macro\" || state.lastToken == \"type\" ||\n state.lastToken == \"struct\" || state.lastToken == \"immutable\";\n\n if (stream.match(identifiers)) {\n if (isDefinition) {\n if (stream.peek() === '.') {\n state.isDefinition = true;\n return \"variable\";\n }\n state.isDefinition = false;\n return \"def\";\n }\n state.leavingExpr = true;\n return \"variable\";\n }\n\n // Handle non-detected items\n stream.next();\n return \"error\";\n}\n\nfunction tokenAnnotation(stream, state) {\n stream.match(/.*?(?=[,;{}()=\\s]|$)/);\n if (stream.match('{')) {\n state.nestedParameters++;\n } else if (stream.match('}') && state.nestedParameters > 0) {\n state.nestedParameters--;\n }\n if (state.nestedParameters > 0) {\n stream.match(/.*?(?={|})/) || stream.next();\n } else if (state.nestedParameters == 0) {\n state.tokenize = tokenBase;\n }\n return \"builtin\";\n}\n\nfunction tokenComment(stream, state) {\n if (stream.match('#=')) {\n state.nestedComments++;\n }\n if (!stream.match(/.*?(?=(#=|=#))/)) {\n stream.skipToEnd();\n }\n if (stream.match('=#')) {\n state.nestedComments--;\n if (state.nestedComments == 0)\n state.tokenize = tokenBase;\n }\n return \"comment\";\n}\n\nfunction tokenChar(stream, state) {\n var isChar = false, match;\n if (stream.match(chars)) {\n isChar = true;\n } else if (match = stream.match(/\\\\u([a-f0-9]{1,4})(?=')/i)) {\n var value = parseInt(match[1], 16);\n if (value <= 55295 || value >= 57344) { // (U+0,U+D7FF), (U+E000,U+FFFF)\n isChar = true;\n stream.next();\n }\n } else if (match = stream.match(/\\\\U([A-Fa-f0-9]{5,8})(?=')/)) {\n var value = parseInt(match[1], 16);\n if (value <= 1114111) { // U+10FFFF\n isChar = true;\n stream.next();\n }\n }\n if (isChar) {\n state.leavingExpr = true;\n state.tokenize = tokenBase;\n return \"string\";\n }\n if (!stream.match(/^[^']+(?=')/)) { stream.skipToEnd(); }\n if (stream.match(\"'\")) { state.tokenize = tokenBase; }\n return \"error\";\n}\n\nfunction tokenStringFactory(delimiter) {\n if (delimiter.substr(-3) === '\"\"\"') {\n delimiter = '\"\"\"';\n } else if (delimiter.substr(-1) === '\"') {\n delimiter = '\"';\n }\n function tokenString(stream, state) {\n if (stream.eat('\\\\')) {\n stream.next();\n } else if (stream.match(delimiter)) {\n state.tokenize = tokenBase;\n state.leavingExpr = true;\n return \"string\";\n } else {\n stream.eat(/[`\"]/);\n }\n stream.eatWhile(/[^\\\\`\"]/);\n return \"string\";\n }\n return tokenString;\n}\n\nexport const julia = {\n name: \"julia\",\n startState: function() {\n return {\n tokenize: tokenBase,\n scopes: [],\n lastToken: null,\n leavingExpr: false,\n isDefinition: false,\n nestedArrays: 0,\n nestedComments: 0,\n nestedGenerators: 0,\n nestedParameters: 0,\n firstParenPos: -1\n };\n },\n\n token: function(stream, state) {\n var style = state.tokenize(stream, state);\n var current = stream.current();\n\n if (current && style) {\n state.lastToken = current;\n }\n\n return style;\n },\n\n indent: function(state, textAfter, cx) {\n var delta = 0;\n if ( textAfter === ']' || textAfter === ')' || /^end\\b/.test(textAfter) ||\n /^else/.test(textAfter) || /^catch\\b/.test(textAfter) || /^elseif\\b/.test(textAfter) ||\n /^finally/.test(textAfter) ) {\n delta = -1;\n }\n return (state.scopes.length + delta) * cx.unit;\n },\n\n languageData: {\n indentOnInput: /^\\s*(end|else|catch|finally)\\b$/,\n commentTokens: {line: \"#\", block: {open: \"#=\", close: \"=#\"}},\n closeBrackets: {brackets: [\"(\", \"[\", \"{\", '\"']},\n autocomplete: keywordsList.concat(builtinsList)\n }\n};\n"],"names":["wordRegexp","words","end","pre","RegExp","join","asciiOperatorsList","operators","delimiters","identifiers","chars","keywordsList","builtinsList","openers","closers","keywords","builtins","macro","symbol","stringPrefixes","macroOperators","symbolOperators","inArray","state","nestedArrays","currentScope","n","scopes","length","tokenBase","stream","match","tokenize","tokenComment","leavingExpr","sol","eatSpace","delimiter","ch","peek","skipToEnd","push","nestedGenerators","pop","inGenerator","lastToken","tokenAnnotation","imMatcher","numberLiteral","tokenChar","current","substr","eat","next","eatWhile","isDefinition","nestedParameters","nestedComments","isChar","value","parseInt","julia","name","startState","firstParenPos","token","style","indent","textAfter","cx","delta","test","unit","languageData","indentOnInput","commentTokens","line","block","open","close","closeBrackets","brackets","autocomplete","concat"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/1118.index.js b/book/_build/html/_static/1118.index.js
new file mode 100644
index 0000000..87e3520
--- /dev/null
+++ b/book/_build/html/_static/1118.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[1118],{1118:(e,t,a)=>{a.r(t),a.d(t,{ebnf:()=>c});const c={name:"ebnf",startState:function(){return{stringType:null,commentType:null,braced:0,lhs:!0,localState:null,stack:[],inDefinition:!1}},token:function(e,t){if(e){switch(0===t.stack.length&&('"'==e.peek()||"'"==e.peek()?(t.stringType=e.peek(),e.next(),t.stack.unshift(1)):e.match("/*")?(t.stack.unshift(0),t.commentType=0):e.match("(*")&&(t.stack.unshift(0),t.commentType=1)),t.stack[0]){case 1:for(;1===t.stack[0]&&!e.eol();)e.peek()===t.stringType?(e.next(),t.stack.shift()):"\\"===e.peek()?(e.next(),e.next()):e.match(/^.[^\\\"\']*/);return t.lhs?"property":"string";case 0:for(;0===t.stack[0]&&!e.eol();)0===t.commentType&&e.match("*/")||1===t.commentType&&e.match("*)")?(t.stack.shift(),t.commentType=null):e.match(/^.[^\*]*/);return"comment";case 2:for(;2===t.stack[0]&&!e.eol();)e.match(/^[^\]\\]+/)||e.match(".")||t.stack.shift();return"operator"}var a=e.peek();switch(a){case"[":return e.next(),t.stack.unshift(2),"bracket";case":":case"|":case";":return e.next(),"operator";case"%":if(e.match("%%"))return"header";if(e.match(/[%][A-Za-z]+/))return"keyword";if(e.match(/[%][}]/))return"bracket";break;case"/":if(e.match(/[\/][A-Za-z]+/))return"keyword";case"\\":if(e.match(/[\][a-z]+/))return"string.special";case".":if(e.match("."))return"atom";case"*":case"-":case"+":case"^":if(e.match(a))return"atom";case"$":if(e.match("$$"))return"builtin";if(e.match(/[$][0-9]+/))return"variableName.special";case"<":if(e.match(/<<[a-zA-Z_]+>>/))return"builtin"}return e.match("//")?(e.skipToEnd(),"comment"):e.match("return")?"operator":e.match(/^[a-zA-Z_][a-zA-Z0-9_]*/)?e.match(/(?=[\(.])/)?"variable":e.match(/(?=[\s\n]*[:=])/)?"def":"variableName.special":-1!=["[","]","(",")"].indexOf(e.peek())?(e.next(),"bracket"):(e.eatSpace()||e.next(),null)}}}}}]);
+//# sourceMappingURL=1118.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/1118.index.js.map b/book/_build/html/_static/1118.index.js.map
new file mode 100644
index 0000000..b794a82
--- /dev/null
+++ b/book/_build/html/_static/1118.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"1118.index.js","mappings":"yHAGO,MAAMA,EAAO,CAClBC,KAAM,OACNC,WAAY,WACV,MAAO,CACLC,WAAY,KACZC,YAAa,KACbC,OAAQ,EACRC,KAAK,EACLC,WAAY,KACZC,MAAO,GACPC,cAAc,EAElB,EACAC,MAAO,SAAUC,EAAQC,GACvB,GAAKD,EAAL,CAoBA,OAjB2B,IAAvBC,EAAMJ,MAAMK,SAEQ,KAAjBF,EAAOG,QAAoC,KAAjBH,EAAOG,QACpCF,EAAMT,WAAaQ,EAAOG,OAC1BH,EAAOI,OACPH,EAAMJ,MAAMQ,QAxBkB,IAyBrBL,EAAOM,MAAM,OACtBL,EAAMJ,MAAMQ,QA1BM,GA2BlBJ,EAAMR,YA5BY,GA6BTO,EAAOM,MAAM,QACtBL,EAAMJ,MAAMQ,QA7BM,GA8BlBJ,EAAMR,YA/B4B,IAqC9BQ,EAAMJ,MAAM,IACpB,KArCkC,EAsChC,KAtCgC,IAsCzBI,EAAMJ,MAAM,KAA6BG,EAAOO,OACjDP,EAAOG,SAAWF,EAAMT,YAC1BQ,EAAOI,OACPH,EAAMJ,MAAMW,SACe,OAAlBR,EAAOG,QAChBH,EAAOI,OACPJ,EAAOI,QAEPJ,EAAOM,MAAM,gBAGjB,OAAOL,EAAMN,IAAM,WAAa,SAElC,KAnDsB,EAoDpB,KApDoB,IAoDbM,EAAMJ,MAAM,KAA6BG,EAAOO,OArDnC,IAsDdN,EAAMR,aAAqCO,EAAOM,MAAM,OAtD1B,IAyDvBL,EAAMR,aAA2CO,EAAOM,MAAM,OAFvEL,EAAMJ,MAAMW,QACZP,EAAMR,YAAc,MAKpBO,EAAOM,MAAM,YAGjB,MAAO,UAET,KAjEqD,EAkEnD,KAlEmD,IAkE5CL,EAAMJ,MAAM,KAAoCG,EAAOO,OACtDP,EAAOM,MAAM,cAAgBN,EAAOM,MAAM,MAC9CL,EAAMJ,MAAMW,QAGhB,MAAO,WAGT,IAAIL,EAAOH,EAAOG,OAGlB,OAAQA,GACR,IAAK,IAGH,OAFAH,EAAOI,OACPH,EAAMJ,MAAMQ,QAhFuC,GAiF5C,UACT,IAAK,IACL,IAAK,IACL,IAAK,IAEH,OADAL,EAAOI,OACA,WACT,IAAK,IACH,GAAIJ,EAAOM,MAAM,MACf,MAAO,SACF,GAAIN,EAAOM,MAAM,gBACtB,MAAO,UACF,GAAIN,EAAOM,MAAM,UACtB,MAAO,UAET,MACF,IAAK,IACH,GAAIN,EAAOM,MAAM,iBACf,MAAO,UAEX,IAAK,KACH,GAAIN,EAAOM,MAAM,aACf,MAAO,iBAEX,IAAK,IACH,GAAIN,EAAOM,MAAM,KACf,MAAO,OAEX,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACH,GAAIN,EAAOM,MAAMH,GACf,MAAO,OAEX,IAAK,IACH,GAAIH,EAAOM,MAAM,MACf,MAAO,UACF,GAAIN,EAAOM,MAAM,aACtB,MAAO,uBAEX,IAAK,IACH,GAAIN,EAAOM,MAAM,kBACf,MAAO,UAIX,OAAIN,EAAOM,MAAM,OACfN,EAAOS,YACA,WACET,EAAOM,MAAM,UACf,WACEN,EAAOM,MAAM,2BAClBN,EAAOM,MAAM,aACR,WACEN,EAAOM,MAAM,mBACf,MAEF,wBACkD,GAAhD,CAAC,IAAK,IAAK,IAAK,KAAKI,QAAQV,EAAOG,SAC7CH,EAAOI,OACA,YACGJ,EAAOW,YACjBX,EAAOI,OAEF,KAjIY,CAkIrB,E","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/ebnf.js"],"sourcesContent":["var commentType = {slash: 0, parenthesis: 1};\nvar stateType = {comment: 0, _string: 1, characterClass: 2};\n\nexport const ebnf = {\n name: \"ebnf\",\n startState: function () {\n return {\n stringType: null,\n commentType: null,\n braced: 0,\n lhs: true,\n localState: null,\n stack: [],\n inDefinition: false\n };\n },\n token: function (stream, state) {\n if (!stream) return;\n\n //check for state changes\n if (state.stack.length === 0) {\n //strings\n if ((stream.peek() == '\"') || (stream.peek() == \"'\")) {\n state.stringType = stream.peek();\n stream.next(); // Skip quote\n state.stack.unshift(stateType._string);\n } else if (stream.match('/*')) { //comments starting with /*\n state.stack.unshift(stateType.comment);\n state.commentType = commentType.slash;\n } else if (stream.match('(*')) { //comments starting with (*\n state.stack.unshift(stateType.comment);\n state.commentType = commentType.parenthesis;\n }\n }\n\n //return state\n //stack has\n switch (state.stack[0]) {\n case stateType._string:\n while (state.stack[0] === stateType._string && !stream.eol()) {\n if (stream.peek() === state.stringType) {\n stream.next(); // Skip quote\n state.stack.shift(); // Clear flag\n } else if (stream.peek() === \"\\\\\") {\n stream.next();\n stream.next();\n } else {\n stream.match(/^.[^\\\\\\\"\\']*/);\n }\n }\n return state.lhs ? \"property\" : \"string\"; // Token style\n\n case stateType.comment:\n while (state.stack[0] === stateType.comment && !stream.eol()) {\n if (state.commentType === commentType.slash && stream.match('*/')) {\n state.stack.shift(); // Clear flag\n state.commentType = null;\n } else if (state.commentType === commentType.parenthesis && stream.match('*)')) {\n state.stack.shift(); // Clear flag\n state.commentType = null;\n } else {\n stream.match(/^.[^\\*]*/);\n }\n }\n return \"comment\";\n\n case stateType.characterClass:\n while (state.stack[0] === stateType.characterClass && !stream.eol()) {\n if (!(stream.match(/^[^\\]\\\\]+/) || stream.match('.'))) {\n state.stack.shift();\n }\n }\n return \"operator\";\n }\n\n var peek = stream.peek();\n\n //no stack\n switch (peek) {\n case \"[\":\n stream.next();\n state.stack.unshift(stateType.characterClass);\n return \"bracket\";\n case \":\":\n case \"|\":\n case \";\":\n stream.next();\n return \"operator\";\n case \"%\":\n if (stream.match(\"%%\")) {\n return \"header\";\n } else if (stream.match(/[%][A-Za-z]+/)) {\n return \"keyword\";\n } else if (stream.match(/[%][}]/)) {\n return \"bracket\";\n }\n break;\n case \"/\":\n if (stream.match(/[\\/][A-Za-z]+/)) {\n return \"keyword\";\n }\n case \"\\\\\":\n if (stream.match(/[\\][a-z]+/)) {\n return \"string.special\";\n }\n case \".\":\n if (stream.match(\".\")) {\n return \"atom\";\n }\n case \"*\":\n case \"-\":\n case \"+\":\n case \"^\":\n if (stream.match(peek)) {\n return \"atom\";\n }\n case \"$\":\n if (stream.match(\"$$\")) {\n return \"builtin\";\n } else if (stream.match(/[$][0-9]+/)) {\n return \"variableName.special\";\n }\n case \"<\":\n if (stream.match(/<<[a-zA-Z_]+>>/)) {\n return \"builtin\";\n }\n }\n\n if (stream.match('//')) {\n stream.skipToEnd();\n return \"comment\";\n } else if (stream.match('return')) {\n return \"operator\";\n } else if (stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/)) {\n if (stream.match(/(?=[\\(.])/)) {\n return \"variable\";\n } else if (stream.match(/(?=[\\s\\n]*[:=])/)) {\n return \"def\";\n }\n return \"variableName.special\";\n } else if ([\"[\", \"]\", \"(\", \")\"].indexOf(stream.peek()) != -1) {\n stream.next();\n return \"bracket\";\n } else if (!stream.eatSpace()) {\n stream.next();\n }\n return null;\n }\n};\n"],"names":["ebnf","name","startState","stringType","commentType","braced","lhs","localState","stack","inDefinition","token","stream","state","length","peek","next","unshift","match","eol","shift","skipToEnd","indexOf","eatSpace"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/1327.index.js b/book/_build/html/_static/1327.index.js
new file mode 100644
index 0000000..d2bc912
--- /dev/null
+++ b/book/_build/html/_static/1327.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[1327],{1327:(e,t,r)=>{function i(e){var t,r;e?(t=/^(exx?|(ld|cp)([di]r?)?|[lp]ea|pop|push|ad[cd]|cpl|daa|dec|inc|neg|sbc|sub|and|bit|[cs]cf|x?or|res|set|r[lr]c?a?|r[lr]d|s[lr]a|srl|djnz|nop|[de]i|halt|im|in([di]mr?|ir?|irx|2r?)|ot(dmr?|[id]rx|imr?)|out(0?|[di]r?|[di]2r?)|tst(io)?|slp)(\.([sl]?i)?[sl])?\b/i,r=/^(((call|j[pr]|rst|ret[in]?)(\.([sl]?i)?[sl])?)|(rs|st)mix)\b/i):(t=/^(exx?|(ld|cp|in)([di]r?)?|pop|push|ad[cd]|cpl|daa|dec|inc|neg|sbc|sub|and|bit|[cs]cf|x?or|res|set|r[lr]c?a?|r[lr]d|s[lr]a|srl|djnz|nop|rst|[de]i|halt|im|ot[di]r|out[di]?)\b/i,r=/^(call|j[pr]|ret[in]?|b_?(call|jump))\b/i);var i=/^(af?|bc?|c|de?|e|hl?|l|i[xy]?|r|sp)\b/i,n=/^(n?[zc]|p[oe]?|m)\b/i,l=/^([hl][xy]|i[xy][hl]|slia|sll)\b/i,a=/^([\da-f]+h|[0-7]+o|[01]+b|\d+d?)\b/i;return{name:"z80",startState:function(){return{context:0}},token:function(s,c){if(s.column()||(c.context=0),s.eatSpace())return null;var u;if(s.eatWhile(/\w/)){if(e&&s.eat(".")&&s.eatWhile(/\w/),u=s.current(),!s.indentation())return s.match(a)?"number":null;if((1==c.context||4==c.context)&&i.test(u))return c.context=4,"variable";if(2==c.context&&n.test(u))return c.context=4,"variableName.special";if(t.test(u))return c.context=1,"keyword";if(r.test(u))return c.context=2,"keyword";if(4==c.context&&a.test(u))return"number";if(l.test(u))return"error"}else{if(s.eat(";"))return s.skipToEnd(),"comment";if(s.eat('"')){for(;(u=s.next())&&'"'!=u;)"\\"==u&&s.next();return"string"}if(s.eat("'")){if(s.match(/\\?.'/))return"number"}else if(s.eat(".")||s.sol()&&s.eat("#")){if(c.context=5,s.eatWhile(/\w/))return"def"}else if(s.eat("$")){if(s.eatWhile(/[\da-f]/i))return"number"}else if(s.eat("%")){if(s.eatWhile(/[01]/))return"number"}else s.next()}return null}}}r.r(t),r.d(t,{ez80:()=>l,z80:()=>n});const n=i(!1),l=i(!0)}}]);
+//# sourceMappingURL=1327.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/1327.index.js.map b/book/_build/html/_static/1327.index.js.map
new file mode 100644
index 0000000..a97b89e
--- /dev/null
+++ b/book/_build/html/_static/1327.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"1327.index.js","mappings":"8FAAA,SAASA,EAAMC,GACb,IAAIC,EAAWC,EACXF,GACFC,EAAY,mQACZC,EAAY,mEAEZD,EAAY,iLACZC,EAAY,4CAGd,IAAIC,EAAa,0CACbC,EAAa,wBACbC,EAAS,oCACTC,EAAU,uCAEd,MAAO,CACLC,KAAM,MACNC,WAAY,WACV,MAAO,CACLC,QAAS,EAEb,EACAC,MAAO,SAASC,EAAQC,GAItB,GAHKD,EAAOE,WACVD,EAAMH,QAAU,GAEdE,EAAOG,WACT,OAAO,KAET,IAAIC,EAEJ,GAAIJ,EAAOK,SAAS,MAAO,CAMzB,GALIhB,GAAQW,EAAOM,IAAI,MACrBN,EAAOK,SAAS,MAElBD,EAAIJ,EAAOO,WAEPP,EAAOQ,cAuBJ,OAAIR,EAAOS,MAAMd,GACf,SAEA,KAzBP,IAAsB,GAAjBM,EAAMH,SAAiC,GAAjBG,EAAMH,UAAiBN,EAAWkB,KAAKN,GAEhE,OADAH,EAAMH,QAAU,EACT,WAGT,GAAqB,GAAjBG,EAAMH,SAAgBL,EAAWiB,KAAKN,GAExC,OADAH,EAAMH,QAAU,EACT,uBAGT,GAAIR,EAAUoB,KAAKN,GAEjB,OADAH,EAAMH,QAAU,EACT,UACF,GAAIP,EAAUmB,KAAKN,GAExB,OADAH,EAAMH,QAAU,EACT,UACF,GAAqB,GAAjBG,EAAMH,SAAgBH,EAAQe,KAAKN,GAC5C,MAAO,SAGT,GAAIV,EAAOgB,KAAKN,GACd,MAAO,OAMb,KAAO,IAAIJ,EAAOM,IAAI,KAEpB,OADAN,EAAOW,YACA,UACF,GAAIX,EAAOM,IAAI,KAAM,CAC1B,MAAOF,EAAIJ,EAAOY,SACP,KAALR,GAGK,MAALA,GACFJ,EAAOY,OAEX,MAAO,QACT,CAAO,GAAIZ,EAAOM,IAAI,MACpB,GAAIN,EAAOS,MAAM,SACf,MAAO,cACJ,GAAIT,EAAOM,IAAI,MAAQN,EAAOa,OAASb,EAAOM,IAAI,MAGvD,GAFAL,EAAMH,QAAU,EAEZE,EAAOK,SAAS,MAClB,MAAO,WACJ,GAAIL,EAAOM,IAAI,MACpB,GAAIN,EAAOK,SAAS,YAClB,MAAO,cACJ,GAAIL,EAAOM,IAAI,MACpB,GAAIN,EAAOK,SAAS,QAClB,MAAO,cAETL,EAAOY,MACT,CACA,OAAO,IACT,EAEJ,C,qCAEO,MAAME,EAAM1B,GAAM,GACZC,EAAOD,GAAM,E","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/z80.js"],"sourcesContent":["function mkZ80(ez80) {\n var keywords1, keywords2;\n if (ez80) {\n keywords1 = /^(exx?|(ld|cp)([di]r?)?|[lp]ea|pop|push|ad[cd]|cpl|daa|dec|inc|neg|sbc|sub|and|bit|[cs]cf|x?or|res|set|r[lr]c?a?|r[lr]d|s[lr]a|srl|djnz|nop|[de]i|halt|im|in([di]mr?|ir?|irx|2r?)|ot(dmr?|[id]rx|imr?)|out(0?|[di]r?|[di]2r?)|tst(io)?|slp)(\\.([sl]?i)?[sl])?\\b/i;\n keywords2 = /^(((call|j[pr]|rst|ret[in]?)(\\.([sl]?i)?[sl])?)|(rs|st)mix)\\b/i;\n } else {\n keywords1 = /^(exx?|(ld|cp|in)([di]r?)?|pop|push|ad[cd]|cpl|daa|dec|inc|neg|sbc|sub|and|bit|[cs]cf|x?or|res|set|r[lr]c?a?|r[lr]d|s[lr]a|srl|djnz|nop|rst|[de]i|halt|im|ot[di]r|out[di]?)\\b/i;\n keywords2 = /^(call|j[pr]|ret[in]?|b_?(call|jump))\\b/i;\n }\n\n var variables1 = /^(af?|bc?|c|de?|e|hl?|l|i[xy]?|r|sp)\\b/i;\n var variables2 = /^(n?[zc]|p[oe]?|m)\\b/i;\n var errors = /^([hl][xy]|i[xy][hl]|slia|sll)\\b/i;\n var numbers = /^([\\da-f]+h|[0-7]+o|[01]+b|\\d+d?)\\b/i;\n\n return {\n name: \"z80\",\n startState: function() {\n return {\n context: 0\n };\n },\n token: function(stream, state) {\n if (!stream.column())\n state.context = 0;\n\n if (stream.eatSpace())\n return null;\n\n var w;\n\n if (stream.eatWhile(/\\w/)) {\n if (ez80 && stream.eat('.')) {\n stream.eatWhile(/\\w/);\n }\n w = stream.current();\n\n if (stream.indentation()) {\n if ((state.context == 1 || state.context == 4) && variables1.test(w)) {\n state.context = 4;\n return 'variable';\n }\n\n if (state.context == 2 && variables2.test(w)) {\n state.context = 4;\n return 'variableName.special';\n }\n\n if (keywords1.test(w)) {\n state.context = 1;\n return 'keyword';\n } else if (keywords2.test(w)) {\n state.context = 2;\n return 'keyword';\n } else if (state.context == 4 && numbers.test(w)) {\n return 'number';\n }\n\n if (errors.test(w))\n return 'error';\n } else if (stream.match(numbers)) {\n return 'number';\n } else {\n return null;\n }\n } else if (stream.eat(';')) {\n stream.skipToEnd();\n return 'comment';\n } else if (stream.eat('\"')) {\n while (w = stream.next()) {\n if (w == '\"')\n break;\n\n if (w == '\\\\')\n stream.next();\n }\n return 'string';\n } else if (stream.eat('\\'')) {\n if (stream.match(/\\\\?.'/))\n return 'number';\n } else if (stream.eat('.') || stream.sol() && stream.eat('#')) {\n state.context = 5;\n\n if (stream.eatWhile(/\\w/))\n return 'def';\n } else if (stream.eat('$')) {\n if (stream.eatWhile(/[\\da-f]/i))\n return 'number';\n } else if (stream.eat('%')) {\n if (stream.eatWhile(/[01]/))\n return 'number';\n } else {\n stream.next();\n }\n return null;\n }\n };\n};\n\nexport const z80 = mkZ80(false)\nexport const ez80 = mkZ80(true)\n"],"names":["mkZ80","ez80","keywords1","keywords2","variables1","variables2","errors","numbers","name","startState","context","token","stream","state","column","eatSpace","w","eatWhile","eat","current","indentation","match","test","skipToEnd","next","sol","z80"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/1363.index.js b/book/_build/html/_static/1363.index.js
new file mode 100644
index 0000000..58321eb
--- /dev/null
+++ b/book/_build/html/_static/1363.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[1363],{71363:(e,t,T)=>{function n(e){for(var t={},T=e.split(" "),n=0;nR});const E={name:"ttcn-cfg",keywords:n("Yes No LogFile FileMask ConsoleMask AppendFile TimeStampFormat LogEventTypes SourceInfoFormat LogEntityName LogSourceInfo DiskFullAction LogFileNumber LogFileSize MatchingHints Detailed Compact SubCategories Stack Single None Seconds DateTime Time Stop Error Retry Delete TCPPort KillTimer NumHCs UnixSocketsEnabled LocalAddress"),fileNCtrlMaskOptions:n("TTCN_EXECUTOR TTCN_ERROR TTCN_WARNING TTCN_PORTEVENT TTCN_TIMEROP TTCN_VERDICTOP TTCN_DEFAULTOP TTCN_TESTCASE TTCN_ACTION TTCN_USER TTCN_FUNCTION TTCN_STATISTICS TTCN_PARALLEL TTCN_MATCHING TTCN_DEBUG EXECUTOR ERROR WARNING PORTEVENT TIMEROP VERDICTOP DEFAULTOP TESTCASE ACTION USER FUNCTION STATISTICS PARALLEL MATCHING DEBUG LOG_ALL LOG_NOTHING ACTION_UNQUALIFIED DEBUG_ENCDEC DEBUG_TESTPORT DEBUG_UNQUALIFIED DEFAULTOP_ACTIVATE DEFAULTOP_DEACTIVATE DEFAULTOP_EXIT DEFAULTOP_UNQUALIFIED ERROR_UNQUALIFIED EXECUTOR_COMPONENT EXECUTOR_CONFIGDATA EXECUTOR_EXTCOMMAND EXECUTOR_LOGOPTIONS EXECUTOR_RUNTIME EXECUTOR_UNQUALIFIED FUNCTION_RND FUNCTION_UNQUALIFIED MATCHING_DONE MATCHING_MCSUCCESS MATCHING_MCUNSUCC MATCHING_MMSUCCESS MATCHING_MMUNSUCC MATCHING_PCSUCCESS MATCHING_PCUNSUCC MATCHING_PMSUCCESS MATCHING_PMUNSUCC MATCHING_PROBLEM MATCHING_TIMEOUT MATCHING_UNQUALIFIED PARALLEL_PORTCONN PARALLEL_PORTMAP PARALLEL_PTC PARALLEL_UNQUALIFIED PORTEVENT_DUALRECV PORTEVENT_DUALSEND PORTEVENT_MCRECV PORTEVENT_MCSEND PORTEVENT_MMRECV PORTEVENT_MMSEND PORTEVENT_MQUEUE PORTEVENT_PCIN PORTEVENT_PCOUT PORTEVENT_PMIN PORTEVENT_PMOUT PORTEVENT_PQUEUE PORTEVENT_STATE PORTEVENT_UNQUALIFIED STATISTICS_UNQUALIFIED STATISTICS_VERDICT TESTCASE_FINISH TESTCASE_START TESTCASE_UNQUALIFIED TIMEROP_GUARD TIMEROP_READ TIMEROP_START TIMEROP_STOP TIMEROP_TIMEOUT TIMEROP_UNQUALIFIED USER_UNQUALIFIED VERDICTOP_FINAL VERDICTOP_GETVERDICT VERDICTOP_SETVERDICT VERDICTOP_UNQUALIFIED WARNING_UNQUALIFIED"),externalCommands:n("BeginControlPart EndControlPart BeginTestCase EndTestCase"),multiLineStrings:!0};var C,N=E.keywords,I=E.fileNCtrlMaskOptions,r=E.externalCommands,i=E.multiLineStrings,o=!1!==E.indentStatements,_=/[\|]/;function A(e,t){var T,n=e.next();if('"'==n||"'"==n)return t.tokenize=(T=n,function(e,t){for(var n,E=!1,C=!1;null!=(n=e.next());){if(n==T&&!E){var N=e.peek();N&&("b"!=(N=N.toLowerCase())&&"h"!=N&&"o"!=N||e.next()),C=!0;break}E=!E&&"\\"==n}return(C||!E&&!i)&&(t.tokenize=null),"string"}),t.tokenize(e,t);if(/[:=]/.test(n))return C=n,"punctuation";if("#"==n)return e.skipToEnd(),"comment";if(/\d/.test(n))return e.eatWhile(/[\w\.]/),"number";if(_.test(n))return e.eatWhile(_),"operator";if("["==n)return e.eatWhile(/[\w_\]]/),"number";e.eatWhile(/[\w\$_]/);var E=e.current();return N.propertyIsEnumerable(E)?"keyword":I.propertyIsEnumerable(E)?"atom":r.propertyIsEnumerable(E)?"deleted":"variable"}function O(e,t,T,n,E){this.indented=e,this.column=t,this.type=T,this.align=n,this.prev=E}function U(e,t,T){var n=e.indented;return e.context&&"statement"==e.context.type&&(n=e.context.indented),e.context=new O(n,t,T,null,e.context)}function a(e){var t=e.context.type;return")"!=t&&"]"!=t&&"}"!=t||(e.indented=e.context.indented),e.context=e.context.prev}const R={name:"ttcn",startState:function(){return{tokenize:null,context:new O(0,0,"top",!1),indented:0,startOfLine:!0}},token:function(e,t){var T=t.context;if(e.sol()&&(null==T.align&&(T.align=!1),t.indented=e.indentation(),t.startOfLine=!0),e.eatSpace())return null;C=null;var n=(t.tokenize||A)(e,t);if("comment"==n)return n;if(null==T.align&&(T.align=!0),";"!=C&&":"!=C&&","!=C||"statement"!=T.type)if("{"==C)U(t,e.column(),"}");else if("["==C)U(t,e.column(),"]");else if("("==C)U(t,e.column(),")");else if("}"==C){for(;"statement"==T.type;)T=a(t);for("}"==T.type&&(T=a(t));"statement"==T.type;)T=a(t)}else C==T.type?a(t):o&&(("}"==T.type||"top"==T.type)&&";"!=C||"statement"==T.type&&"newstatement"==C)&&U(t,e.column(),"statement");else a(t);return t.startOfLine=!1,n},languageData:{indentOnInput:/^\s*[{}]$/,commentTokens:{line:"#"}}}}}]);
+//# sourceMappingURL=1363.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/1363.index.js.map b/book/_build/html/_static/1363.index.js.map
new file mode 100644
index 0000000..143db22
--- /dev/null
+++ b/book/_build/html/_static/1363.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"1363.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/ttcn-cfg.js"],"sourcesContent":["function words(str) {\n var obj = {}, words = str.split(\" \");\n for (var i = 0; i < words.length; ++i)\n obj[words[i]] = true;\n return obj;\n}\n\nconst parserConfig = {\n name: \"ttcn-cfg\",\n keywords: words(\"Yes No LogFile FileMask ConsoleMask AppendFile\" +\n \" TimeStampFormat LogEventTypes SourceInfoFormat\" +\n \" LogEntityName LogSourceInfo DiskFullAction\" +\n \" LogFileNumber LogFileSize MatchingHints Detailed\" +\n \" Compact SubCategories Stack Single None Seconds\" +\n \" DateTime Time Stop Error Retry Delete TCPPort KillTimer\" +\n \" NumHCs UnixSocketsEnabled LocalAddress\"),\n fileNCtrlMaskOptions: words(\"TTCN_EXECUTOR TTCN_ERROR TTCN_WARNING\" +\n \" TTCN_PORTEVENT TTCN_TIMEROP TTCN_VERDICTOP\" +\n \" TTCN_DEFAULTOP TTCN_TESTCASE TTCN_ACTION\" +\n \" TTCN_USER TTCN_FUNCTION TTCN_STATISTICS\" +\n \" TTCN_PARALLEL TTCN_MATCHING TTCN_DEBUG\" +\n \" EXECUTOR ERROR WARNING PORTEVENT TIMEROP\" +\n \" VERDICTOP DEFAULTOP TESTCASE ACTION USER\" +\n \" FUNCTION STATISTICS PARALLEL MATCHING DEBUG\" +\n \" LOG_ALL LOG_NOTHING ACTION_UNQUALIFIED\" +\n \" DEBUG_ENCDEC DEBUG_TESTPORT\" +\n \" DEBUG_UNQUALIFIED DEFAULTOP_ACTIVATE\" +\n \" DEFAULTOP_DEACTIVATE DEFAULTOP_EXIT\" +\n \" DEFAULTOP_UNQUALIFIED ERROR_UNQUALIFIED\" +\n \" EXECUTOR_COMPONENT EXECUTOR_CONFIGDATA\" +\n \" EXECUTOR_EXTCOMMAND EXECUTOR_LOGOPTIONS\" +\n \" EXECUTOR_RUNTIME EXECUTOR_UNQUALIFIED\" +\n \" FUNCTION_RND FUNCTION_UNQUALIFIED\" +\n \" MATCHING_DONE MATCHING_MCSUCCESS\" +\n \" MATCHING_MCUNSUCC MATCHING_MMSUCCESS\" +\n \" MATCHING_MMUNSUCC MATCHING_PCSUCCESS\" +\n \" MATCHING_PCUNSUCC MATCHING_PMSUCCESS\" +\n \" MATCHING_PMUNSUCC MATCHING_PROBLEM\" +\n \" MATCHING_TIMEOUT MATCHING_UNQUALIFIED\" +\n \" PARALLEL_PORTCONN PARALLEL_PORTMAP\" +\n \" PARALLEL_PTC PARALLEL_UNQUALIFIED\" +\n \" PORTEVENT_DUALRECV PORTEVENT_DUALSEND\" +\n \" PORTEVENT_MCRECV PORTEVENT_MCSEND\" +\n \" PORTEVENT_MMRECV PORTEVENT_MMSEND\" +\n \" PORTEVENT_MQUEUE PORTEVENT_PCIN\" +\n \" PORTEVENT_PCOUT PORTEVENT_PMIN\" +\n \" PORTEVENT_PMOUT PORTEVENT_PQUEUE\" +\n \" PORTEVENT_STATE PORTEVENT_UNQUALIFIED\" +\n \" STATISTICS_UNQUALIFIED STATISTICS_VERDICT\" +\n \" TESTCASE_FINISH TESTCASE_START\" +\n \" TESTCASE_UNQUALIFIED TIMEROP_GUARD\" +\n \" TIMEROP_READ TIMEROP_START TIMEROP_STOP\" +\n \" TIMEROP_TIMEOUT TIMEROP_UNQUALIFIED\" +\n \" USER_UNQUALIFIED VERDICTOP_FINAL\" +\n \" VERDICTOP_GETVERDICT VERDICTOP_SETVERDICT\" +\n \" VERDICTOP_UNQUALIFIED WARNING_UNQUALIFIED\"),\n externalCommands: words(\"BeginControlPart EndControlPart BeginTestCase\" +\n \" EndTestCase\"),\n multiLineStrings: true\n}\n\nvar keywords = parserConfig.keywords,\n fileNCtrlMaskOptions = parserConfig.fileNCtrlMaskOptions,\n externalCommands = parserConfig.externalCommands,\n multiLineStrings = parserConfig.multiLineStrings,\n indentStatements = parserConfig.indentStatements !== false;\nvar isOperatorChar = /[\\|]/;\nvar curPunc;\n\nfunction tokenBase(stream, state) {\n var ch = stream.next();\n if (ch == '\"' || ch == \"'\") {\n state.tokenize = tokenString(ch);\n return state.tokenize(stream, state);\n }\n if (/[:=]/.test(ch)) {\n curPunc = ch;\n return \"punctuation\";\n }\n if (ch == \"#\"){\n stream.skipToEnd();\n return \"comment\";\n }\n if (/\\d/.test(ch)) {\n stream.eatWhile(/[\\w\\.]/);\n return \"number\";\n }\n if (isOperatorChar.test(ch)) {\n stream.eatWhile(isOperatorChar);\n return \"operator\";\n }\n if (ch == \"[\"){\n stream.eatWhile(/[\\w_\\]]/);\n return \"number\";\n }\n\n stream.eatWhile(/[\\w\\$_]/);\n var cur = stream.current();\n if (keywords.propertyIsEnumerable(cur)) return \"keyword\";\n if (fileNCtrlMaskOptions.propertyIsEnumerable(cur))\n return \"atom\";\n if (externalCommands.propertyIsEnumerable(cur)) return \"deleted\";\n\n return \"variable\";\n}\n\nfunction tokenString(quote) {\n return function(stream, state) {\n var escaped = false, next, end = false;\n while ((next = stream.next()) != null) {\n if (next == quote && !escaped){\n var afterNext = stream.peek();\n //look if the character if the quote is like the B in '10100010'B\n if (afterNext){\n afterNext = afterNext.toLowerCase();\n if(afterNext == \"b\" || afterNext == \"h\" || afterNext == \"o\")\n stream.next();\n }\n end = true; break;\n }\n escaped = !escaped && next == \"\\\\\";\n }\n if (end || !(escaped || multiLineStrings))\n state.tokenize = null;\n return \"string\";\n };\n}\n\nfunction Context(indented, column, type, align, prev) {\n this.indented = indented;\n this.column = column;\n this.type = type;\n this.align = align;\n this.prev = prev;\n}\nfunction pushContext(state, col, type) {\n var indent = state.indented;\n if (state.context && state.context.type == \"statement\")\n indent = state.context.indented;\n return state.context = new Context(indent, col, type, null, state.context);\n}\nfunction popContext(state) {\n var t = state.context.type;\n if (t == \")\" || t == \"]\" || t == \"}\")\n state.indented = state.context.indented;\n return state.context = state.context.prev;\n}\n\n//Interface\nexport const ttcnCfg = {\n name: \"ttcn\",\n startState: function() {\n return {\n tokenize: null,\n context: new Context(0, 0, \"top\", false),\n indented: 0,\n startOfLine: true\n };\n },\n\n token: function(stream, state) {\n var ctx = state.context;\n if (stream.sol()) {\n if (ctx.align == null) ctx.align = false;\n state.indented = stream.indentation();\n state.startOfLine = true;\n }\n if (stream.eatSpace()) return null;\n curPunc = null;\n var style = (state.tokenize || tokenBase)(stream, state);\n if (style == \"comment\") return style;\n if (ctx.align == null) ctx.align = true;\n\n if ((curPunc == \";\" || curPunc == \":\" || curPunc == \",\")\n && ctx.type == \"statement\"){\n popContext(state);\n }\n else if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n else if (curPunc == \"}\") {\n while (ctx.type == \"statement\") ctx = popContext(state);\n if (ctx.type == \"}\") ctx = popContext(state);\n while (ctx.type == \"statement\") ctx = popContext(state);\n }\n else if (curPunc == ctx.type) popContext(state);\n else if (indentStatements && (((ctx.type == \"}\" || ctx.type == \"top\")\n && curPunc != ';') || (ctx.type == \"statement\"\n && curPunc == \"newstatement\")))\n pushContext(state, stream.column(), \"statement\");\n state.startOfLine = false;\n return style;\n },\n\n languageData: {\n indentOnInput: /^\\s*[{}]$/,\n commentTokens: {line: \"#\"}\n }\n};\n"],"names":["words","str","obj","split","i","length","parserConfig","name","keywords","fileNCtrlMaskOptions","externalCommands","multiLineStrings","curPunc","indentStatements","isOperatorChar","tokenBase","stream","state","quote","ch","next","tokenize","escaped","end","afterNext","peek","toLowerCase","test","skipToEnd","eatWhile","cur","current","propertyIsEnumerable","Context","indented","column","type","align","prev","this","pushContext","col","indent","context","popContext","t","ttcnCfg","startState","startOfLine","token","ctx","sol","indentation","eatSpace","style","languageData","indentOnInput","commentTokens","line"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/1620.index.js b/book/_build/html/_static/1620.index.js
new file mode 100644
index 0000000..b471bf9
--- /dev/null
+++ b/book/_build/html/_static/1620.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[1620],{21620:(e,n,t)=>{function i(e,n){for(var t=0;tk});var a={unnamedDefinition:["interface"],namedDefinition:["module","library","macro","C-struct","C-union","C-function","C-callable-wrapper"],typeParameterizedDefinition:["class","C-subtype","C-mapped-subtype"],otherParameterizedDefinition:["method","function","C-variable","C-address"],constantSimpleDefinition:["constant"],variableSimpleDefinition:["variable"],otherSimpleDefinition:["generic","domain","C-pointer-type","table"],statement:["if","block","begin","method","case","for","select","when","unless","until","while","iterate","profiling","dynamic-bind"],separator:["finally","exception","cleanup","else","elseif","afterwards"],other:["above","below","by","from","handler","in","instance","let","local","otherwise","slot","subclass","then","to","keyed-by","virtual"],signalingCalls:["signal","error","cerror","break","check-type","abort"]};a.otherDefinition=a.unnamedDefinition.concat(a.namedDefinition).concat(a.otherParameterizedDefinition),a.definition=a.typeParameterizedDefinition.concat(a.otherDefinition),a.parameterizedDefinition=a.typeParameterizedDefinition.concat(a.otherParameterizedDefinition),a.simpleDefinition=a.constantSimpleDefinition.concat(a.variableSimpleDefinition).concat(a.otherSimpleDefinition),a.keyword=a.statement.concat(a.separator).concat(a.other);var o="[-_a-zA-Z?!*@<>$%]+",l=new RegExp("^"+o),f={symbolKeyword:o+":",symbolClass:"<"+o+">",symbolGlobal:"\\*"+o+"\\*",symbolConstant:"\\$"+o},c={symbolKeyword:"atom",symbolClass:"tag",symbolGlobal:"variableName.standard",symbolConstant:"variableName.constant"};for(var s in f)f.hasOwnProperty(s)&&(f[s]=new RegExp("^"+f[s]));f.keyword=[/^with(?:out)?-[-_a-zA-Z?!*@<>$%]+/];var u={keyword:"keyword",definition:"def",simpleDefinition:"def",signalingCalls:"builtin"},m={},d={};function p(e,n,t){return n.tokenize=t,t(e,n)}function b(e,n){var t=e.peek();if("'"==t||'"'==t)return e.next(),p(e,n,y(t,"string"));if("/"==t){if(e.next(),e.eat("*"))return p(e,n,h);if(e.eat("/"))return e.skipToEnd(),"comment";e.backUp(1)}else if(/[+\-\d\.]/.test(t)){if(e.match(/^[+-]?[0-9]*\.[0-9]*([esdx][+-]?[0-9]+)?/i)||e.match(/^[+-]?[0-9]+([esdx][+-]?[0-9]+)/i)||e.match(/^[+-]?\d+/))return"number"}else{if("#"==t)return e.next(),'"'==(t=e.peek())?(e.next(),p(e,n,y('"',"string"))):"b"==t?(e.next(),e.eatWhile(/[01]/),"number"):"x"==t?(e.next(),e.eatWhile(/[\da-f]/i),"number"):"o"==t?(e.next(),e.eatWhile(/[0-7]/),"number"):"#"==t?(e.next(),"punctuation"):"["==t||"("==t?(e.next(),"bracket"):e.match(/f|t|all-keys|include|key|next|rest/i)?"atom":(e.eatWhile(/[-a-zA-Z]/),"error");if("~"==t)return e.next(),"="==(t=e.peek())?(e.next(),"="==(t=e.peek())?(e.next(),"operator"):"operator"):"operator";if(":"==t){if(e.next(),"="==(t=e.peek()))return e.next(),"operator";if(":"==t)return e.next(),"punctuation"}else{if(-1!="[](){}".indexOf(t))return e.next(),"bracket";if(-1!=".,".indexOf(t))return e.next(),"punctuation";if(e.match("end"))return"keyword"}}for(var i in f)if(f.hasOwnProperty(i)){var a=f[i];if(a instanceof Array&&r(a,(function(n){return e.match(n)}))||e.match(a))return c[i]}return/[+\-*\/^=<>&|]/.test(t)?(e.next(),"operator"):e.match("define")?"def":(e.eatWhile(/[\w\-]/),m.hasOwnProperty(e.current())?d[e.current()]:e.current().match(l)?"variable":(e.next(),"variableName.standard"))}function h(e,n){for(var t,i=!1,r=!1,a=0;t=e.next();){if("/"==t&&i){if(!(a>0)){n.tokenize=b;break}a--}else"*"==t&&r&&a++;i="*"==t,r="/"==t}return"comment"}function y(e,n){return function(t,i){for(var r,a=!1,o=!1;null!=(r=t.next());){if(r==e&&!a){o=!0;break}a=!a&&"\\"==r}return!o&&a||(i.tokenize=b),n}}i(["keyword","definition","simpleDefinition","signalingCalls"],(function(e){i(a[e],(function(n){m[n]=e,d[n]=u[e]}))}));const k={name:"dylan",startState:function(){return{tokenize:b,currentIndent:0}},token:function(e,n){return e.eatSpace()?null:n.tokenize(e,n)},languageData:{commentTokens:{block:{open:"/*",close:"*/"}}}}}}]);
+//# sourceMappingURL=1620.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/1620.index.js.map b/book/_build/html/_static/1620.index.js.map
new file mode 100644
index 0000000..6c0176f
--- /dev/null
+++ b/book/_build/html/_static/1620.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"1620.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/dylan.js"],"sourcesContent":["function forEach(arr, f) {\n for (var i = 0; i < arr.length; i++) f(arr[i], i)\n}\nfunction some(arr, f) {\n for (var i = 0; i < arr.length; i++) if (f(arr[i], i)) return true\n return false\n}\n\n// Words\nvar words = {\n // Words that introduce unnamed definitions like \"define interface\"\n unnamedDefinition: [\"interface\"],\n\n // Words that introduce simple named definitions like \"define library\"\n namedDefinition: [\"module\", \"library\", \"macro\",\n \"C-struct\", \"C-union\",\n \"C-function\", \"C-callable-wrapper\"\n ],\n\n // Words that introduce type definitions like \"define class\".\n // These are also parameterized like \"define method\" and are\n // appended to otherParameterizedDefinitionWords\n typeParameterizedDefinition: [\"class\", \"C-subtype\", \"C-mapped-subtype\"],\n\n // Words that introduce trickier definitions like \"define method\".\n // These require special definitions to be added to startExpressions\n otherParameterizedDefinition: [\"method\", \"function\",\n \"C-variable\", \"C-address\"\n ],\n\n // Words that introduce module constant definitions.\n // These must also be simple definitions and are\n // appended to otherSimpleDefinitionWords\n constantSimpleDefinition: [\"constant\"],\n\n // Words that introduce module variable definitions.\n // These must also be simple definitions and are\n // appended to otherSimpleDefinitionWords\n variableSimpleDefinition: [\"variable\"],\n\n // Other words that introduce simple definitions\n // (without implicit bodies).\n otherSimpleDefinition: [\"generic\", \"domain\",\n \"C-pointer-type\",\n \"table\"\n ],\n\n // Words that begin statements with implicit bodies.\n statement: [\"if\", \"block\", \"begin\", \"method\", \"case\",\n \"for\", \"select\", \"when\", \"unless\", \"until\",\n \"while\", \"iterate\", \"profiling\", \"dynamic-bind\"\n ],\n\n // Patterns that act as separators in compound statements.\n // This may include any general pattern that must be indented\n // specially.\n separator: [\"finally\", \"exception\", \"cleanup\", \"else\",\n \"elseif\", \"afterwards\"\n ],\n\n // Keywords that do not require special indentation handling,\n // but which should be highlighted\n other: [\"above\", \"below\", \"by\", \"from\", \"handler\", \"in\",\n \"instance\", \"let\", \"local\", \"otherwise\", \"slot\",\n \"subclass\", \"then\", \"to\", \"keyed-by\", \"virtual\"\n ],\n\n // Condition signaling function calls\n signalingCalls: [\"signal\", \"error\", \"cerror\",\n \"break\", \"check-type\", \"abort\"\n ]\n};\n\nwords[\"otherDefinition\"] =\n words[\"unnamedDefinition\"]\n .concat(words[\"namedDefinition\"])\n .concat(words[\"otherParameterizedDefinition\"]);\n\nwords[\"definition\"] =\n words[\"typeParameterizedDefinition\"]\n .concat(words[\"otherDefinition\"]);\n\nwords[\"parameterizedDefinition\"] =\n words[\"typeParameterizedDefinition\"]\n .concat(words[\"otherParameterizedDefinition\"]);\n\nwords[\"simpleDefinition\"] =\n words[\"constantSimpleDefinition\"]\n .concat(words[\"variableSimpleDefinition\"])\n .concat(words[\"otherSimpleDefinition\"]);\n\nwords[\"keyword\"] =\n words[\"statement\"]\n .concat(words[\"separator\"])\n .concat(words[\"other\"]);\n\n// Patterns\nvar symbolPattern = \"[-_a-zA-Z?!*@<>$%]+\";\nvar symbol = new RegExp(\"^\" + symbolPattern);\nvar patterns = {\n // Symbols with special syntax\n symbolKeyword: symbolPattern + \":\",\n symbolClass: \"<\" + symbolPattern + \">\",\n symbolGlobal: \"\\\\*\" + symbolPattern + \"\\\\*\",\n symbolConstant: \"\\\\$\" + symbolPattern\n};\nvar patternStyles = {\n symbolKeyword: \"atom\",\n symbolClass: \"tag\",\n symbolGlobal: \"variableName.standard\",\n symbolConstant: \"variableName.constant\"\n};\n\n// Compile all patterns to regular expressions\nfor (var patternName in patterns)\n if (patterns.hasOwnProperty(patternName))\n patterns[patternName] = new RegExp(\"^\" + patterns[patternName]);\n\n// Names beginning \"with-\" and \"without-\" are commonly\n// used as statement macro\npatterns[\"keyword\"] = [/^with(?:out)?-[-_a-zA-Z?!*@<>$%]+/];\n\nvar styles = {};\nstyles[\"keyword\"] = \"keyword\";\nstyles[\"definition\"] = \"def\";\nstyles[\"simpleDefinition\"] = \"def\";\nstyles[\"signalingCalls\"] = \"builtin\";\n\n// protected words lookup table\nvar wordLookup = {};\nvar styleLookup = {};\n\nforEach([\n \"keyword\",\n \"definition\",\n \"simpleDefinition\",\n \"signalingCalls\"\n], function(type) {\n forEach(words[type], function(word) {\n wordLookup[word] = type;\n styleLookup[word] = styles[type];\n });\n});\n\n\nfunction chain(stream, state, f) {\n state.tokenize = f;\n return f(stream, state);\n}\n\nfunction tokenBase(stream, state) {\n // String\n var ch = stream.peek();\n if (ch == \"'\" || ch == '\"') {\n stream.next();\n return chain(stream, state, tokenString(ch, \"string\"));\n }\n // Comment\n else if (ch == \"/\") {\n stream.next();\n if (stream.eat(\"*\")) {\n return chain(stream, state, tokenComment);\n } else if (stream.eat(\"/\")) {\n stream.skipToEnd();\n return \"comment\";\n }\n stream.backUp(1);\n }\n // Decimal\n else if (/[+\\-\\d\\.]/.test(ch)) {\n if (stream.match(/^[+-]?[0-9]*\\.[0-9]*([esdx][+-]?[0-9]+)?/i) ||\n stream.match(/^[+-]?[0-9]+([esdx][+-]?[0-9]+)/i) ||\n stream.match(/^[+-]?\\d+/)) {\n return \"number\";\n }\n }\n // Hash\n else if (ch == \"#\") {\n stream.next();\n // Symbol with string syntax\n ch = stream.peek();\n if (ch == '\"') {\n stream.next();\n return chain(stream, state, tokenString('\"', \"string\"));\n }\n // Binary number\n else if (ch == \"b\") {\n stream.next();\n stream.eatWhile(/[01]/);\n return \"number\";\n }\n // Hex number\n else if (ch == \"x\") {\n stream.next();\n stream.eatWhile(/[\\da-f]/i);\n return \"number\";\n }\n // Octal number\n else if (ch == \"o\") {\n stream.next();\n stream.eatWhile(/[0-7]/);\n return \"number\";\n }\n // Token concatenation in macros\n else if (ch == '#') {\n stream.next();\n return \"punctuation\";\n }\n // Sequence literals\n else if ((ch == '[') || (ch == '(')) {\n stream.next();\n return \"bracket\";\n // Hash symbol\n } else if (stream.match(/f|t|all-keys|include|key|next|rest/i)) {\n return \"atom\";\n } else {\n stream.eatWhile(/[-a-zA-Z]/);\n return \"error\";\n }\n } else if (ch == \"~\") {\n stream.next();\n ch = stream.peek();\n if (ch == \"=\") {\n stream.next();\n ch = stream.peek();\n if (ch == \"=\") {\n stream.next();\n return \"operator\";\n }\n return \"operator\";\n }\n return \"operator\";\n } else if (ch == \":\") {\n stream.next();\n ch = stream.peek();\n if (ch == \"=\") {\n stream.next();\n return \"operator\";\n } else if (ch == \":\") {\n stream.next();\n return \"punctuation\";\n }\n } else if (\"[](){}\".indexOf(ch) != -1) {\n stream.next();\n return \"bracket\";\n } else if (\".,\".indexOf(ch) != -1) {\n stream.next();\n return \"punctuation\";\n } else if (stream.match(\"end\")) {\n return \"keyword\";\n }\n for (var name in patterns) {\n if (patterns.hasOwnProperty(name)) {\n var pattern = patterns[name];\n if ((pattern instanceof Array && some(pattern, function(p) {\n return stream.match(p);\n })) || stream.match(pattern))\n return patternStyles[name];\n }\n }\n if (/[+\\-*\\/^=<>&|]/.test(ch)) {\n stream.next();\n return \"operator\";\n }\n if (stream.match(\"define\")) {\n return \"def\";\n } else {\n stream.eatWhile(/[\\w\\-]/);\n // Keyword\n if (wordLookup.hasOwnProperty(stream.current())) {\n return styleLookup[stream.current()];\n } else if (stream.current().match(symbol)) {\n return \"variable\";\n } else {\n stream.next();\n return \"variableName.standard\";\n }\n }\n}\n\nfunction tokenComment(stream, state) {\n var maybeEnd = false, maybeNested = false, nestedCount = 0, ch;\n while ((ch = stream.next())) {\n if (ch == \"/\" && maybeEnd) {\n if (nestedCount > 0) {\n nestedCount--;\n } else {\n state.tokenize = tokenBase;\n break;\n }\n } else if (ch == \"*\" && maybeNested) {\n nestedCount++;\n }\n maybeEnd = (ch == \"*\");\n maybeNested = (ch == \"/\");\n }\n return \"comment\";\n}\n\nfunction tokenString(quote, style) {\n return function(stream, state) {\n var escaped = false, next, end = false;\n while ((next = stream.next()) != null) {\n if (next == quote && !escaped) {\n end = true;\n break;\n }\n escaped = !escaped && next == \"\\\\\";\n }\n if (end || !escaped) {\n state.tokenize = tokenBase;\n }\n return style;\n };\n}\n\n// Interface\nexport const dylan = {\n name: \"dylan\",\n startState: function() {\n return {\n tokenize: tokenBase,\n currentIndent: 0\n };\n },\n token: function(stream, state) {\n if (stream.eatSpace())\n return null;\n var style = state.tokenize(stream, state);\n return style;\n },\n languageData: {\n commentTokens: {block: {open: \"/*\", close: \"*/\"}}\n }\n};\n\n"],"names":["forEach","arr","f","i","length","some","words","unnamedDefinition","namedDefinition","typeParameterizedDefinition","otherParameterizedDefinition","constantSimpleDefinition","variableSimpleDefinition","otherSimpleDefinition","statement","separator","other","signalingCalls","concat","symbolPattern","symbol","RegExp","patterns","symbolKeyword","symbolClass","symbolGlobal","symbolConstant","patternStyles","patternName","hasOwnProperty","styles","wordLookup","styleLookup","chain","stream","state","tokenize","tokenBase","ch","peek","next","tokenString","eat","tokenComment","skipToEnd","backUp","test","match","eatWhile","indexOf","name","pattern","Array","p","current","maybeEnd","maybeNested","nestedCount","quote","style","escaped","end","type","word","dylan","startState","currentIndent","token","eatSpace","languageData","commentTokens","block","open","close"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/1643.index.js b/book/_build/html/_static/1643.index.js
new file mode 100644
index 0000000..7d22e97
--- /dev/null
+++ b/book/_build/html/_static/1643.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[1643],{31643:(a,e,n)=>{n.r(e),n.d(e,{gherkin:()=>i});const i={name:"gherkin",startState:function(){return{lineNumber:0,tableHeaderLine:!1,allowFeature:!0,allowBackground:!1,allowScenario:!1,allowSteps:!1,allowPlaceholders:!1,allowMultilineArgument:!1,inMultilineString:!1,inMultilineTable:!1,inKeywordLine:!1}},token:function(a,e){if(a.sol()&&(e.lineNumber++,e.inKeywordLine=!1,e.inMultilineTable&&(e.tableHeaderLine=!1,a.match(/\s*\|/,!1)||(e.allowMultilineArgument=!1,e.inMultilineTable=!1))),a.eatSpace(),e.allowMultilineArgument){if(e.inMultilineString)return a.match('"""')?(e.inMultilineString=!1,e.allowMultilineArgument=!1):a.match(/.*/),"string";if(e.inMultilineTable)return a.match(/\|\s*/)?"bracket":(a.match(/[^\|]*/),e.tableHeaderLine?"header":"string");if(a.match('"""'))return e.inMultilineString=!0,"string";if(a.match("|"))return e.inMultilineTable=!0,e.tableHeaderLine=!0,"bracket"}return a.match(/#.*/)?"comment":!e.inKeywordLine&&a.match(/@\S+/)?"tag":!e.inKeywordLine&&e.allowFeature&&a.match(/(機能|功能|フィーチャ|기능|โครงหลัก|ความสามารถ|ความต้องการทางธุรกิจ|ಹೆಚ್ಚಳ|గుణము|ਮੁਹਾਂਦਰਾ|ਨਕਸ਼ ਨੁਹਾਰ|ਖਾਸੀਅਤ|रूप लेख|وِیژگی|خاصية|תכונה|Функціонал|Функция|Функционалност|Функционал|Үзенчәлеклелек|Свойство|Особина|Мөмкинлек|Могућност|Λειτουργία|Δυνατότητα|Właściwość|Vlastnosť|Trajto|Tính năng|Savybė|Pretty much|Požiadavka|Požadavek|Potrzeba biznesowa|Özellik|Osobina|Ominaisuus|Omadus|OH HAI|Mogućnost|Mogucnost|Jellemző|Hwæt|Hwaet|Funzionalità|Funktionalitéit|Funktionalität|Funkcja|Funkcionalnost|Funkcionalitāte|Funkcia|Fungsi|Functionaliteit|Funcționalitate|Funcţionalitate|Functionalitate|Funcionalitat|Funcionalidade|Fonctionnalité|Fitur|Fīča|Feature|Eiginleiki|Egenskap|Egenskab|Característica|Caracteristica|Business Need|Aspekt|Arwedd|Ahoy matey!|Ability):/)?(e.allowScenario=!0,e.allowBackground=!0,e.allowPlaceholders=!1,e.allowSteps=!1,e.allowMultilineArgument=!1,e.inKeywordLine=!0,"keyword"):!e.inKeywordLine&&e.allowBackground&&a.match(/(背景|배경|แนวคิด|ಹಿನ್ನೆಲೆ|నేపథ్యం|ਪਿਛੋਕੜ|पृष्ठभूमि|زمینه|الخلفية|רקע|Тарих|Предыстория|Предистория|Позадина|Передумова|Основа|Контекст|Кереш|Υπόβαθρο|Założenia|Yo\-ho\-ho|Tausta|Taust|Situācija|Rerefons|Pozadina|Pozadie|Pozadí|Osnova|Latar Belakang|Kontext|Konteksts|Kontekstas|Kontekst|Háttér|Hannergrond|Grundlage|Geçmiş|Fundo|Fono|First off|Dis is what went down|Dasar|Contexto|Contexte|Context|Contesto|Cenário de Fundo|Cenario de Fundo|Cefndir|Bối cảnh|Bakgrunnur|Bakgrunn|Bakgrund|Baggrund|Background|B4|Antecedents|Antecedentes|Ær|Aer|Achtergrond):/)?(e.allowPlaceholders=!1,e.allowSteps=!0,e.allowBackground=!1,e.allowMultilineArgument=!1,e.inKeywordLine=!0,"keyword"):!e.inKeywordLine&&e.allowScenario&&a.match(/(場景大綱|场景大纲|劇本大綱|剧本大纲|テンプレ|シナリオテンプレート|シナリオテンプレ|シナリオアウトライン|시나리오 개요|สรุปเหตุการณ์|โครงสร้างของเหตุการณ์|ವಿವರಣೆ|కథనం|ਪਟਕਥਾ ਰੂਪ ਰੇਖਾ|ਪਟਕਥਾ ਢਾਂਚਾ|परिदृश्य रूपरेखा|سيناريو مخطط|الگوی سناریو|תבנית תרחיש|Сценарийның төзелеше|Сценарий структураси|Структура сценарію|Структура сценария|Структура сценарија|Скица|Рамка на сценарий|Концепт|Περιγραφή Σεναρίου|Wharrimean is|Template Situai|Template Senario|Template Keadaan|Tapausaihio|Szenariogrundriss|Szablon scenariusza|Swa hwær swa|Swa hwaer swa|Struktura scenarija|Structură scenariu|Structura scenariu|Skica|Skenario konsep|Shiver me timbers|Senaryo taslağı|Schema dello scenario|Scenariomall|Scenariomal|Scenario Template|Scenario Outline|Scenario Amlinellol|Scenārijs pēc parauga|Scenarijaus šablonas|Reckon it's like|Raamstsenaarium|Plang vum Szenario|Plan du Scénario|Plan du scénario|Osnova scénáře|Osnova Scenára|Náčrt Scenáru|Náčrt Scénáře|Náčrt Scenára|MISHUN SRSLY|Menggariskan Senario|Lýsing Dæma|Lýsing Atburðarásar|Konturo de la scenaro|Koncept|Khung tình huống|Khung kịch bản|Forgatókönyv vázlat|Esquema do Cenário|Esquema do Cenario|Esquema del escenario|Esquema de l'escenari|Esbozo do escenario|Delineação do Cenário|Delineacao do Cenario|All y'all|Abstrakt Scenario|Abstract Scenario):/)?(e.allowPlaceholders=!0,e.allowSteps=!0,e.allowMultilineArgument=!1,e.inKeywordLine=!0,"keyword"):e.allowScenario&&a.match(/(例子|例|サンプル|예|ชุดของเหตุการณ์|ชุดของตัวอย่าง|ಉದಾಹರಣೆಗಳು|ఉదాహరణలు|ਉਦਾਹਰਨਾਂ|उदाहरण|نمونه ها|امثلة|דוגמאות|Үрнәкләр|Сценарији|Примеры|Примери|Приклади|Мисоллар|Мисаллар|Σενάρια|Παραδείγματα|You'll wanna|Voorbeelden|Variantai|Tapaukset|Se þe|Se the|Se ðe|Scenarios|Scenariji|Scenarijai|Przykłady|Primjeri|Primeri|Příklady|Príklady|Piemēri|Példák|Pavyzdžiai|Paraugs|Örnekler|Juhtumid|Exemplos|Exemples|Exemple|Exempel|EXAMPLZ|Examples|Esempi|Enghreifftiau|Ekzemploj|Eksempler|Ejemplos|Dữ liệu|Dead men tell no tales|Dæmi|Contoh|Cenários|Cenarios|Beispiller|Beispiele|Atburðarásir):/)?(e.allowPlaceholders=!1,e.allowSteps=!0,e.allowBackground=!1,e.allowMultilineArgument=!0,"keyword"):!e.inKeywordLine&&e.allowScenario&&a.match(/(場景|场景|劇本|剧本|シナリオ|시나리오|เหตุการณ์|ಕಥಾಸಾರಾಂಶ|సన్నివేశం|ਪਟਕਥਾ|परिदृश्य|سيناريو|سناریو|תרחיש|Сценарій|Сценарио|Сценарий|Пример|Σενάριο|Tình huống|The thing of it is|Tapaus|Szenario|Swa|Stsenaarium|Skenario|Situai|Senaryo|Senario|Scenaro|Scenariusz|Scenariu|Scénario|Scenario|Scenarijus|Scenārijs|Scenarij|Scenarie|Scénář|Scenár|Primer|MISHUN|Kịch bản|Keadaan|Heave to|Forgatókönyv|Escenario|Escenari|Cenário|Cenario|Awww, look mate|Atburðarás):/)?(e.allowPlaceholders=!1,e.allowSteps=!0,e.allowBackground=!1,e.allowMultilineArgument=!1,e.inKeywordLine=!0,"keyword"):!e.inKeywordLine&&e.allowSteps&&a.match(/(那麼|那么|而且|當|当|并且|同時|同时|前提|假设|假設|假定|假如|但是|但し|並且|もし|ならば|ただし|しかし|かつ|하지만|조건|먼저|만일|만약|단|그리고|그러면|และ |เมื่อ |แต่ |ดังนั้น |กำหนดให้ |ಸ್ಥಿತಿಯನ್ನು |ಮತ್ತು |ನೀಡಿದ |ನಂತರ |ಆದರೆ |మరియు |చెప్పబడినది |కాని |ఈ పరిస్థితిలో |అప్పుడు |ਪਰ |ਤਦ |ਜੇਕਰ |ਜਿਵੇਂ ਕਿ |ਜਦੋਂ |ਅਤੇ |यदि |परन्तु |पर |तब |तदा |तथा |जब |चूंकि |किन्तु |कदा |और |अगर |و |هنگامی |متى |لكن |عندما |ثم |بفرض |با فرض |اما |اذاً |آنگاه |כאשר |וגם |בהינתן |אזי |אז |אבל |Якщо |Һәм |Унда |Тоді |Тогда |То |Также |Та |Пусть |Припустимо, що |Припустимо |Онда |Но |Нехай |Нәтиҗәдә |Лекин |Ләкин |Коли |Когда |Когато |Када |Кад |К тому же |І |И |Задато |Задати |Задате |Если |Допустим |Дано |Дадено |Вә |Ва |Бирок |Әмма |Әйтик |Әгәр |Аммо |Али |Але |Агар |А також |А |Τότε |Όταν |Και |Δεδομένου |Αλλά |Þurh |Þegar |Þa þe |Þá |Þa |Zatati |Zakładając |Zadato |Zadate |Zadano |Zadani |Zadan |Za předpokladu |Za predpokladu |Youse know when youse got |Youse know like when |Yna |Yeah nah |Y'know |Y |Wun |Wtedy |When y'all |When |Wenn |WEN |wann |Ve |Và |Und |Un |ugeholl |Too right |Thurh |Thì |Then y'all |Then |Tha the |Tha |Tetapi |Tapi |Tak |Tada |Tad |Stel |Soit |Siis |Și |Şi |Si |Sed |Se |Så |Quando |Quand |Quan |Pryd |Potom |Pokud |Pokiaľ |Però |Pero |Pak |Oraz |Onda |Ond |Oletetaan |Og |Och |O zaman |Niin |Nhưng |När |Når |Mutta |Men |Mas |Maka |Majd |Mając |Mais |Maar |mä |Ma |Lorsque |Lorsqu'|Logo |Let go and haul |Kun |Kuid |Kui |Kiedy |Khi |Ketika |Kemudian |Keď |Když |Kaj |Kai |Kada |Kad |Jeżeli |Jeśli |Ja |It's just unbelievable |Ir |I CAN HAZ |I |Ha |Givun |Givet |Given y'all |Given |Gitt |Gegeven |Gegeben seien |Gegeben sei |Gdy |Gangway! |Fakat |Étant donnés |Etant donnés |Étant données |Etant données |Étant donnée |Etant donnée |Étant donné |Etant donné |Et |És |Entonces |Entón |Então |Entao |En |Eğer ki |Ef |Eeldades |E |Ðurh |Duota |Dun |Donitaĵo |Donat |Donada |Do |Diyelim ki |Diberi |Dengan |Den youse gotta |DEN |De |Dato |Dați fiind |Daţi fiind |Dati fiind |Dati |Date fiind |Date |Data |Dat fiind |Dar |Dann |dann |Dan |Dados |Dado |Dadas |Dada |Ða ðe |Ða |Cuando |Cho |Cando |Când |Cand |Cal |But y'all |But at the end of the day I reckon |BUT |But |Buh |Blimey! |Biết |Bet |Bagi |Aye |awer |Avast! |Atunci |Atesa |Atès |Apabila |Anrhegedig a |Angenommen |And y'all |And |AN |An |an |Amikor |Amennyiben |Ama |Als |Alors |Allora |Ali |Aleshores |Ale |Akkor |Ak |Adott |Ac |Aber |A zároveň |A tiež |A taktiež |A také |A |a |7 |\* )/)?(e.inStep=!0,e.allowPlaceholders=!0,e.allowMultilineArgument=!0,e.inKeywordLine=!0,"keyword"):a.match(/"[^"]*"?/)?"string":e.allowPlaceholders&&a.match(/<[^>]*>?/)?"variable":(a.next(),a.eatWhile(/[^@"<#]/),null)}}}}]);
+//# sourceMappingURL=1643.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/1643.index.js.map b/book/_build/html/_static/1643.index.js.map
new file mode 100644
index 0000000..d6c0afc
--- /dev/null
+++ b/book/_build/html/_static/1643.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"1643.index.js","mappings":"6HAAO,MAAMA,EAAU,CACrBC,KAAM,UACNC,WAAY,WACV,MAAO,CACLC,WAAY,EACZC,iBAAiB,EACjBC,cAAc,EACdC,iBAAiB,EACjBC,eAAe,EACfC,YAAY,EACZC,mBAAmB,EACnBC,wBAAwB,EACxBC,mBAAmB,EACnBC,kBAAkB,EAClBC,eAAe,EAEnB,EACAC,MAAO,SAAUC,EAAQC,GAevB,GAdID,EAAOE,QACTD,EAAMb,aACNa,EAAMH,eAAgB,EAClBG,EAAMJ,mBACRI,EAAMZ,iBAAkB,EACnBW,EAAOG,MAAM,SAAS,KACzBF,EAAMN,wBAAyB,EAC/BM,EAAMJ,kBAAmB,KAK/BG,EAAOI,WAEHH,EAAMN,uBAAwB,CAGhC,GAAIM,EAAML,kBAOR,OANII,EAAOG,MAAM,QACfF,EAAML,mBAAoB,EAC1BK,EAAMN,wBAAyB,GAE/BK,EAAOG,MAAM,MAER,SAIT,GAAIF,EAAMJ,iBACR,OAAIG,EAAOG,MAAM,SACR,WAEPH,EAAOG,MAAM,UACNF,EAAMZ,gBAAkB,SAAW,UAK9C,GAAIW,EAAOG,MAAM,OAGf,OADAF,EAAML,mBAAoB,EACnB,SACF,GAAII,EAAOG,MAAM,KAItB,OAFAF,EAAMJ,kBAAmB,EACzBI,EAAMZ,iBAAkB,EACjB,SAGX,CAGA,OAAIW,EAAOG,MAAM,OACR,WAGGF,EAAMH,eAAiBE,EAAOG,MAAM,QACvC,OAGGF,EAAMH,eAAiBG,EAAMX,cAAgBU,EAAOG,MAAM,svBACpEF,EAAMT,eAAgB,EACtBS,EAAMV,iBAAkB,EACxBU,EAAMP,mBAAoB,EAC1BO,EAAMR,YAAa,EACnBQ,EAAMN,wBAAyB,EAC/BM,EAAMH,eAAgB,EACf,YAGGG,EAAMH,eAAiBG,EAAMV,iBAAmBS,EAAOG,MAAM,6iBACvEF,EAAMP,mBAAoB,EAC1BO,EAAMR,YAAa,EACnBQ,EAAMV,iBAAkB,EACxBU,EAAMN,wBAAyB,EAC/BM,EAAMH,eAAgB,EACf,YAGGG,EAAMH,eAAiBG,EAAMT,eAAiBQ,EAAOG,MAAM,kuCACrEF,EAAMP,mBAAoB,EAC1BO,EAAMR,YAAa,EACnBQ,EAAMN,wBAAyB,EAC/BM,EAAMH,eAAgB,EACf,WAGEG,EAAMT,eAAiBQ,EAAOG,MAAM,okBAC7CF,EAAMP,mBAAoB,EAC1BO,EAAMR,YAAa,EACnBQ,EAAMV,iBAAkB,EACxBU,EAAMN,wBAAyB,EACxB,YAGGM,EAAMH,eAAiBG,EAAMT,eAAiBQ,EAAOG,MAAM,6bACrEF,EAAMP,mBAAoB,EAC1BO,EAAMR,YAAa,EACnBQ,EAAMV,iBAAkB,EACxBU,EAAMN,wBAAyB,EAC/BM,EAAMH,eAAgB,EACf,YAGGG,EAAMH,eAAiBG,EAAMR,YAAcO,EAAOG,MAAM,y2EAClEF,EAAMI,QAAS,EACfJ,EAAMP,mBAAoB,EAC1BO,EAAMN,wBAAyB,EAC/BM,EAAMH,eAAgB,EACf,WAGEE,EAAOG,MAAM,YACf,SAGEF,EAAMP,mBAAqBM,EAAOG,MAAM,YAC1C,YAIPH,EAAOM,OACPN,EAAOO,SAAS,WACT,KAEX,E","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/gherkin.js"],"sourcesContent":["export const gherkin = {\n name: \"gherkin\",\n startState: function () {\n return {\n lineNumber: 0,\n tableHeaderLine: false,\n allowFeature: true,\n allowBackground: false,\n allowScenario: false,\n allowSteps: false,\n allowPlaceholders: false,\n allowMultilineArgument: false,\n inMultilineString: false,\n inMultilineTable: false,\n inKeywordLine: false\n };\n },\n token: function (stream, state) {\n if (stream.sol()) {\n state.lineNumber++;\n state.inKeywordLine = false;\n if (state.inMultilineTable) {\n state.tableHeaderLine = false;\n if (!stream.match(/\\s*\\|/, false)) {\n state.allowMultilineArgument = false;\n state.inMultilineTable = false;\n }\n }\n }\n\n stream.eatSpace();\n\n if (state.allowMultilineArgument) {\n\n // STRING\n if (state.inMultilineString) {\n if (stream.match('\"\"\"')) {\n state.inMultilineString = false;\n state.allowMultilineArgument = false;\n } else {\n stream.match(/.*/);\n }\n return \"string\";\n }\n\n // TABLE\n if (state.inMultilineTable) {\n if (stream.match(/\\|\\s*/)) {\n return \"bracket\";\n } else {\n stream.match(/[^\\|]*/);\n return state.tableHeaderLine ? \"header\" : \"string\";\n }\n }\n\n // DETECT START\n if (stream.match('\"\"\"')) {\n // String\n state.inMultilineString = true;\n return \"string\";\n } else if (stream.match(\"|\")) {\n // Table\n state.inMultilineTable = true;\n state.tableHeaderLine = true;\n return \"bracket\";\n }\n\n }\n\n // LINE COMMENT\n if (stream.match(/#.*/)) {\n return \"comment\";\n\n // TAG\n } else if (!state.inKeywordLine && stream.match(/@\\S+/)) {\n return \"tag\";\n\n // FEATURE\n } else if (!state.inKeywordLine && state.allowFeature && stream.match(/(機能|功能|フィーチャ|기능|โครงหลัก|ความสามารถ|ความต้องการทางธุรกิจ|ಹೆಚ್ಚಳ|గుణము|ਮੁਹਾਂਦਰਾ|ਨਕਸ਼ ਨੁਹਾਰ|ਖਾਸੀਅਤ|रूप लेख|وِیژگی|خاصية|תכונה|Функціонал|Функция|Функционалност|Функционал|Үзенчәлеклелек|Свойство|Особина|Мөмкинлек|Могућност|Λειτουργία|Δυνατότητα|Właściwość|Vlastnosť|Trajto|Tính năng|Savybė|Pretty much|Požiadavka|Požadavek|Potrzeba biznesowa|Özellik|Osobina|Ominaisuus|Omadus|OH HAI|Mogućnost|Mogucnost|Jellemző|Hwæt|Hwaet|Funzionalità|Funktionalitéit|Funktionalität|Funkcja|Funkcionalnost|Funkcionalitāte|Funkcia|Fungsi|Functionaliteit|Funcționalitate|Funcţionalitate|Functionalitate|Funcionalitat|Funcionalidade|Fonctionnalité|Fitur|Fīča|Feature|Eiginleiki|Egenskap|Egenskab|Característica|Caracteristica|Business Need|Aspekt|Arwedd|Ahoy matey!|Ability):/)) {\n state.allowScenario = true;\n state.allowBackground = true;\n state.allowPlaceholders = false;\n state.allowSteps = false;\n state.allowMultilineArgument = false;\n state.inKeywordLine = true;\n return \"keyword\";\n\n // BACKGROUND\n } else if (!state.inKeywordLine && state.allowBackground && stream.match(/(背景|배경|แนวคิด|ಹಿನ್ನೆಲೆ|నేపథ్యం|ਪਿਛੋਕੜ|पृष्ठभूमि|زمینه|الخلفية|רקע|Тарих|Предыстория|Предистория|Позадина|Передумова|Основа|Контекст|Кереш|Υπόβαθρο|Założenia|Yo\\-ho\\-ho|Tausta|Taust|Situācija|Rerefons|Pozadina|Pozadie|Pozadí|Osnova|Latar Belakang|Kontext|Konteksts|Kontekstas|Kontekst|Háttér|Hannergrond|Grundlage|Geçmiş|Fundo|Fono|First off|Dis is what went down|Dasar|Contexto|Contexte|Context|Contesto|Cenário de Fundo|Cenario de Fundo|Cefndir|Bối cảnh|Bakgrunnur|Bakgrunn|Bakgrund|Baggrund|Background|B4|Antecedents|Antecedentes|Ær|Aer|Achtergrond):/)) {\n state.allowPlaceholders = false;\n state.allowSteps = true;\n state.allowBackground = false;\n state.allowMultilineArgument = false;\n state.inKeywordLine = true;\n return \"keyword\";\n\n // SCENARIO OUTLINE\n } else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景大綱|场景大纲|劇本大綱|剧本大纲|テンプレ|シナリオテンプレート|シナリオテンプレ|シナリオアウトライン|시나리오 개요|สรุปเหตุการณ์|โครงสร้างของเหตุการณ์|ವಿವರಣೆ|కథనం|ਪਟਕਥਾ ਰੂਪ ਰੇਖਾ|ਪਟਕਥਾ ਢਾਂਚਾ|परिदृश्य रूपरेखा|سيناريو مخطط|الگوی سناریو|תבנית תרחיש|Сценарийның төзелеше|Сценарий структураси|Структура сценарію|Структура сценария|Структура сценарија|Скица|Рамка на сценарий|Концепт|Περιγραφή Σεναρίου|Wharrimean is|Template Situai|Template Senario|Template Keadaan|Tapausaihio|Szenariogrundriss|Szablon scenariusza|Swa hwær swa|Swa hwaer swa|Struktura scenarija|Structură scenariu|Structura scenariu|Skica|Skenario konsep|Shiver me timbers|Senaryo taslağı|Schema dello scenario|Scenariomall|Scenariomal|Scenario Template|Scenario Outline|Scenario Amlinellol|Scenārijs pēc parauga|Scenarijaus šablonas|Reckon it's like|Raamstsenaarium|Plang vum Szenario|Plan du Scénario|Plan du scénario|Osnova scénáře|Osnova Scenára|Náčrt Scenáru|Náčrt Scénáře|Náčrt Scenára|MISHUN SRSLY|Menggariskan Senario|Lýsing Dæma|Lýsing Atburðarásar|Konturo de la scenaro|Koncept|Khung tình huống|Khung kịch bản|Forgatókönyv vázlat|Esquema do Cenário|Esquema do Cenario|Esquema del escenario|Esquema de l'escenari|Esbozo do escenario|Delineação do Cenário|Delineacao do Cenario|All y'all|Abstrakt Scenario|Abstract Scenario):/)) {\n state.allowPlaceholders = true;\n state.allowSteps = true;\n state.allowMultilineArgument = false;\n state.inKeywordLine = true;\n return \"keyword\";\n\n // EXAMPLES\n } else if (state.allowScenario && stream.match(/(例子|例|サンプル|예|ชุดของเหตุการณ์|ชุดของตัวอย่าง|ಉದಾಹರಣೆಗಳು|ఉదాహరణలు|ਉਦਾਹਰਨਾਂ|उदाहरण|نمونه ها|امثلة|דוגמאות|Үрнәкләр|Сценарији|Примеры|Примери|Приклади|Мисоллар|Мисаллар|Σενάρια|Παραδείγματα|You'll wanna|Voorbeelden|Variantai|Tapaukset|Se þe|Se the|Se ðe|Scenarios|Scenariji|Scenarijai|Przykłady|Primjeri|Primeri|Příklady|Príklady|Piemēri|Példák|Pavyzdžiai|Paraugs|Örnekler|Juhtumid|Exemplos|Exemples|Exemple|Exempel|EXAMPLZ|Examples|Esempi|Enghreifftiau|Ekzemploj|Eksempler|Ejemplos|Dữ liệu|Dead men tell no tales|Dæmi|Contoh|Cenários|Cenarios|Beispiller|Beispiele|Atburðarásir):/)) {\n state.allowPlaceholders = false;\n state.allowSteps = true;\n state.allowBackground = false;\n state.allowMultilineArgument = true;\n return \"keyword\";\n\n // SCENARIO\n } else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景|场景|劇本|剧本|シナリオ|시나리오|เหตุการณ์|ಕಥಾಸಾರಾಂಶ|సన్నివేశం|ਪਟਕਥਾ|परिदृश्य|سيناريو|سناریو|תרחיש|Сценарій|Сценарио|Сценарий|Пример|Σενάριο|Tình huống|The thing of it is|Tapaus|Szenario|Swa|Stsenaarium|Skenario|Situai|Senaryo|Senario|Scenaro|Scenariusz|Scenariu|Scénario|Scenario|Scenarijus|Scenārijs|Scenarij|Scenarie|Scénář|Scenár|Primer|MISHUN|Kịch bản|Keadaan|Heave to|Forgatókönyv|Escenario|Escenari|Cenário|Cenario|Awww, look mate|Atburðarás):/)) {\n state.allowPlaceholders = false;\n state.allowSteps = true;\n state.allowBackground = false;\n state.allowMultilineArgument = false;\n state.inKeywordLine = true;\n return \"keyword\";\n\n // STEPS\n } else if (!state.inKeywordLine && state.allowSteps && stream.match(/(那麼|那么|而且|當|当|并且|同時|同时|前提|假设|假設|假定|假如|但是|但し|並且|もし|ならば|ただし|しかし|かつ|하지만|조건|먼저|만일|만약|단|그리고|그러면|และ |เมื่อ |แต่ |ดังนั้น |กำหนดให้ |ಸ್ಥಿತಿಯನ್ನು |ಮತ್ತು |ನೀಡಿದ |ನಂತರ |ಆದರೆ |మరియు |చెప్పబడినది |కాని |ఈ పరిస్థితిలో |అప్పుడు |ਪਰ |ਤਦ |ਜੇਕਰ |ਜਿਵੇਂ ਕਿ |ਜਦੋਂ |ਅਤੇ |यदि |परन्तु |पर |तब |तदा |तथा |जब |चूंकि |किन्तु |कदा |और |अगर |و |هنگامی |متى |لكن |عندما |ثم |بفرض |با فرض |اما |اذاً |آنگاه |כאשר |וגם |בהינתן |אזי |אז |אבל |Якщо |Һәм |Унда |Тоді |Тогда |То |Также |Та |Пусть |Припустимо, що |Припустимо |Онда |Но |Нехай |Нәтиҗәдә |Лекин |Ләкин |Коли |Когда |Когато |Када |Кад |К тому же |І |И |Задато |Задати |Задате |Если |Допустим |Дано |Дадено |Вә |Ва |Бирок |Әмма |Әйтик |Әгәр |Аммо |Али |Але |Агар |А також |А |Τότε |Όταν |Και |Δεδομένου |Αλλά |Þurh |Þegar |Þa þe |Þá |Þa |Zatati |Zakładając |Zadato |Zadate |Zadano |Zadani |Zadan |Za předpokladu |Za predpokladu |Youse know when youse got |Youse know like when |Yna |Yeah nah |Y'know |Y |Wun |Wtedy |When y'all |When |Wenn |WEN |wann |Ve |Và |Und |Un |ugeholl |Too right |Thurh |Thì |Then y'all |Then |Tha the |Tha |Tetapi |Tapi |Tak |Tada |Tad |Stel |Soit |Siis |Și |Şi |Si |Sed |Se |Så |Quando |Quand |Quan |Pryd |Potom |Pokud |Pokiaľ |Però |Pero |Pak |Oraz |Onda |Ond |Oletetaan |Og |Och |O zaman |Niin |Nhưng |När |Når |Mutta |Men |Mas |Maka |Majd |Mając |Mais |Maar |mä |Ma |Lorsque |Lorsqu'|Logo |Let go and haul |Kun |Kuid |Kui |Kiedy |Khi |Ketika |Kemudian |Keď |Když |Kaj |Kai |Kada |Kad |Jeżeli |Jeśli |Ja |It's just unbelievable |Ir |I CAN HAZ |I |Ha |Givun |Givet |Given y'all |Given |Gitt |Gegeven |Gegeben seien |Gegeben sei |Gdy |Gangway! |Fakat |Étant donnés |Etant donnés |Étant données |Etant données |Étant donnée |Etant donnée |Étant donné |Etant donné |Et |És |Entonces |Entón |Então |Entao |En |Eğer ki |Ef |Eeldades |E |Ðurh |Duota |Dun |Donitaĵo |Donat |Donada |Do |Diyelim ki |Diberi |Dengan |Den youse gotta |DEN |De |Dato |Dați fiind |Daţi fiind |Dati fiind |Dati |Date fiind |Date |Data |Dat fiind |Dar |Dann |dann |Dan |Dados |Dado |Dadas |Dada |Ða ðe |Ða |Cuando |Cho |Cando |Când |Cand |Cal |But y'all |But at the end of the day I reckon |BUT |But |Buh |Blimey! |Biết |Bet |Bagi |Aye |awer |Avast! |Atunci |Atesa |Atès |Apabila |Anrhegedig a |Angenommen |And y'all |And |AN |An |an |Amikor |Amennyiben |Ama |Als |Alors |Allora |Ali |Aleshores |Ale |Akkor |Ak |Adott |Ac |Aber |A zároveň |A tiež |A taktiež |A také |A |a |7 |\\* )/)) {\n state.inStep = true;\n state.allowPlaceholders = true;\n state.allowMultilineArgument = true;\n state.inKeywordLine = true;\n return \"keyword\";\n\n // INLINE STRING\n } else if (stream.match(/\"[^\"]*\"?/)) {\n return \"string\";\n\n // PLACEHOLDER\n } else if (state.allowPlaceholders && stream.match(/<[^>]*>?/)) {\n return \"variable\";\n\n // Fall through\n } else {\n stream.next();\n stream.eatWhile(/[^@\"<#]/);\n return null;\n }\n }\n};\n\n"],"names":["gherkin","name","startState","lineNumber","tableHeaderLine","allowFeature","allowBackground","allowScenario","allowSteps","allowPlaceholders","allowMultilineArgument","inMultilineString","inMultilineTable","inKeywordLine","token","stream","state","sol","match","eatSpace","inStep","next","eatWhile"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/1649.index.js b/book/_build/html/_static/1649.index.js
new file mode 100644
index 0000000..6b0fa4e
--- /dev/null
+++ b/book/_build/html/_static/1649.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[1649],{1649:(O,T,E)=>{function e(O){for(var T={},E=O.split(" "),e=0;eC});var I="ABS ACOS ARITY ASIN ATAN AVG BAGSIZE BINSTORAGE BLOOM BUILDBLOOM CBRT CEIL CONCAT COR COS COSH COUNT COUNT_STAR COV CONSTANTSIZE CUBEDIMENSIONS DIFF DISTINCT DOUBLEABS DOUBLEAVG DOUBLEBASE DOUBLEMAX DOUBLEMIN DOUBLEROUND DOUBLESUM EXP FLOOR FLOATABS FLOATAVG FLOATMAX FLOATMIN FLOATROUND FLOATSUM GENERICINVOKER INDEXOF INTABS INTAVG INTMAX INTMIN INTSUM INVOKEFORDOUBLE INVOKEFORFLOAT INVOKEFORINT INVOKEFORLONG INVOKEFORSTRING INVOKER ISEMPTY JSONLOADER JSONMETADATA JSONSTORAGE LAST_INDEX_OF LCFIRST LOG LOG10 LOWER LONGABS LONGAVG LONGMAX LONGMIN LONGSUM MAX MIN MAPSIZE MONITOREDUDF NONDETERMINISTIC OUTPUTSCHEMA PIGSTORAGE PIGSTREAMING RANDOM REGEX_EXTRACT REGEX_EXTRACT_ALL REPLACE ROUND SIN SINH SIZE SQRT STRSPLIT SUBSTRING SUM STRINGCONCAT STRINGMAX STRINGMIN STRINGSIZE TAN TANH TOBAG TOKENIZE TOMAP TOP TOTUPLE TRIM TEXTLOADER TUPLESIZE UCFIRST UPPER UTF8STORAGECONVERTER ",N="VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE SHIP CACHE INPUT OUTPUT STDERROR STDIN STDOUT LIMIT SAMPLE LEFT RIGHT FULL EQ GT LT GTE LTE NEQ MATCHES TRUE FALSE DUMP",A="BOOLEAN INT LONG FLOAT DOUBLE CHARARRAY BYTEARRAY BAG TUPLE MAP ",R=e(I),S=e(N),t=e(A),L=/[*+\-%<>=&?:\/!|]/;function r(O,T,E){return T.tokenize=E,E(O,T)}function n(O,T){for(var E,e=!1;E=O.next();){if("/"==E&&e){T.tokenize=U;break}e="*"==E}return"comment"}function U(O,T){var E,e=O.next();return'"'==e||"'"==e?r(O,T,(E=e,function(O,T){for(var e,I=!1,N=!1;null!=(e=O.next());){if(e==E&&!I){N=!0;break}I=!I&&"\\"==e}return!N&&I||(T.tokenize=U),"error"})):/[\[\]{}\(\),;\.]/.test(e)?null:/\d/.test(e)?(O.eatWhile(/[\w\.]/),"number"):"/"==e?O.eat("*")?r(O,T,n):(O.eatWhile(L),"operator"):"-"==e?O.eat("-")?(O.skipToEnd(),"comment"):(O.eatWhile(L),"operator"):L.test(e)?(O.eatWhile(L),"operator"):(O.eatWhile(/[\w\$_]/),S&&S.propertyIsEnumerable(O.current().toUpperCase())&&!O.eat(")")&&!O.eat(".")?"keyword":R&&R.propertyIsEnumerable(O.current().toUpperCase())?"builtin":t&&t.propertyIsEnumerable(O.current().toUpperCase())?"type":"variable")}const C={name:"pig",startState:function(){return{tokenize:U,startOfLine:!0}},token:function(O,T){return O.eatSpace()?null:T.tokenize(O,T)},languageData:{autocomplete:(I+A+N).split(" ")}}}}]);
+//# sourceMappingURL=1649.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/1649.index.js.map b/book/_build/html/_static/1649.index.js.map
new file mode 100644
index 0000000..28fbf5f
--- /dev/null
+++ b/book/_build/html/_static/1649.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"1649.index.js","mappings":"8FAAA,SAASA,EAAMC,GAEb,IADA,IAAIC,EAAM,CAAC,EAAGF,EAAQC,EAAIE,MAAM,KACvBC,EAAI,EAAGA,EAAIJ,EAAMK,SAAUD,EAAGF,EAAIF,EAAMI,KAAM,EACvD,OAAOF,CACT,C,0BAGA,IAAII,EAAY,w3BAYZC,EAAY,mXAOZC,EAAS,mEAETC,EAAWT,EAAMM,GAAYI,EAAWV,EAAMO,GAAYI,EAAQX,EAAMQ,GAExEI,EAAiB,oBAErB,SAASC,EAAMC,EAAQC,EAAOC,GAE5B,OADAD,EAAME,SAAWD,EACVA,EAAEF,EAAQC,EACnB,CAEA,SAASG,EAAaJ,EAAQC,GAG5B,IAFA,IACII,EADAC,GAAQ,EAEND,EAAKL,EAAOO,QAAQ,CACxB,GAAS,KAANF,GAAaC,EAAO,CACrBL,EAAME,SAAWK,EACjB,KACF,CACAF,EAAe,KAAND,CACX,CACA,MAAO,SACT,CAkBA,SAASG,EAAUR,EAAQC,GACzB,IAjBmBQ,EAiBfJ,EAAKL,EAAOO,OAGhB,MAAU,KAANF,GAAmB,KAANA,EACRN,EAAMC,EAAQC,GArBJQ,EAqBuBJ,EApBnC,SAASL,EAAQC,GAEtB,IADA,IAAqBM,EAAjBG,GAAU,EAAaC,GAAM,EACD,OAAzBJ,EAAOP,EAAOO,SAAiB,CACpC,GAAIA,GAAQE,IAAUC,EAAS,CAC7BC,GAAM,EAAM,KACd,CACAD,GAAWA,GAAmB,MAARH,CACxB,CAGA,OAFII,GAAQD,IACVT,EAAME,SAAWK,GACZ,OACT,IAWQ,mBAAmBI,KAAKP,GACvB,KAED,KAAKO,KAAKP,IAChBL,EAAOa,SAAS,UACT,UAGM,KAANR,EACHL,EAAOc,IAAI,KACNf,EAAMC,EAAQC,EAAOG,IAG5BJ,EAAOa,SAASf,GACT,YAIE,KAAJO,EACJL,EAAOc,IAAI,MACZd,EAAOe,YACA,YAGPf,EAAOa,SAASf,GACT,YAIFA,EAAec,KAAKP,IAC3BL,EAAOa,SAASf,GACT,aAIPE,EAAOa,SAAS,WAEZjB,GAAYA,EAASoB,qBAAqBhB,EAAOiB,UAAUC,iBAExDlB,EAAOc,IAAI,OAASd,EAAOc,IAAI,KAC3B,UAGPnB,GAAYA,EAASqB,qBAAqBhB,EAAOiB,UAAUC,eACtD,UAELrB,GAASA,EAAMmB,qBAAqBhB,EAAOiB,UAAUC,eAChD,OAEF,WAEX,CAGO,MAAMC,EAAM,CACjBC,KAAM,MAENC,WAAY,WACV,MAAO,CACLlB,SAAUK,EACVc,aAAa,EAEjB,EAEAC,MAAO,SAASvB,EAAQC,GACtB,OAAGD,EAAOwB,WAAmB,KACjBvB,EAAME,SAASH,EAAQC,EAErC,EAEAwB,aAAc,CACZC,cAAelC,EAAYE,EAASD,GAAWJ,MAAM,M","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/pig.js"],"sourcesContent":["function words(str) {\n var obj = {}, words = str.split(\" \");\n for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n return obj;\n}\n\n// builtin funcs taken from trunk revision 1303237\nvar pBuiltins = \"ABS ACOS ARITY ASIN ATAN AVG BAGSIZE BINSTORAGE BLOOM BUILDBLOOM CBRT CEIL \"\n + \"CONCAT COR COS COSH COUNT COUNT_STAR COV CONSTANTSIZE CUBEDIMENSIONS DIFF DISTINCT DOUBLEABS \"\n + \"DOUBLEAVG DOUBLEBASE DOUBLEMAX DOUBLEMIN DOUBLEROUND DOUBLESUM EXP FLOOR FLOATABS FLOATAVG \"\n + \"FLOATMAX FLOATMIN FLOATROUND FLOATSUM GENERICINVOKER INDEXOF INTABS INTAVG INTMAX INTMIN \"\n + \"INTSUM INVOKEFORDOUBLE INVOKEFORFLOAT INVOKEFORINT INVOKEFORLONG INVOKEFORSTRING INVOKER \"\n + \"ISEMPTY JSONLOADER JSONMETADATA JSONSTORAGE LAST_INDEX_OF LCFIRST LOG LOG10 LOWER LONGABS \"\n + \"LONGAVG LONGMAX LONGMIN LONGSUM MAX MIN MAPSIZE MONITOREDUDF NONDETERMINISTIC OUTPUTSCHEMA \"\n + \"PIGSTORAGE PIGSTREAMING RANDOM REGEX_EXTRACT REGEX_EXTRACT_ALL REPLACE ROUND SIN SINH SIZE \"\n + \"SQRT STRSPLIT SUBSTRING SUM STRINGCONCAT STRINGMAX STRINGMIN STRINGSIZE TAN TANH TOBAG \"\n + \"TOKENIZE TOMAP TOP TOTUPLE TRIM TEXTLOADER TUPLESIZE UCFIRST UPPER UTF8STORAGECONVERTER \";\n\n// taken from QueryLexer.g\nvar pKeywords = \"VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP \"\n + \"JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL \"\n + \"PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE \"\n + \"SHIP CACHE INPUT OUTPUT STDERROR STDIN STDOUT LIMIT SAMPLE LEFT RIGHT FULL EQ GT LT GTE LTE \"\n + \"NEQ MATCHES TRUE FALSE DUMP\";\n\n// data types\nvar pTypes = \"BOOLEAN INT LONG FLOAT DOUBLE CHARARRAY BYTEARRAY BAG TUPLE MAP \";\n\nvar builtins = words(pBuiltins), keywords = words(pKeywords), types = words(pTypes)\n\nvar isOperatorChar = /[*+\\-%<>=&?:\\/!|]/;\n\nfunction chain(stream, state, f) {\n state.tokenize = f;\n return f(stream, state);\n}\n\nfunction tokenComment(stream, state) {\n var isEnd = false;\n var ch;\n while(ch = stream.next()) {\n if(ch == \"/\" && isEnd) {\n state.tokenize = tokenBase;\n break;\n }\n isEnd = (ch == \"*\");\n }\n return \"comment\";\n}\n\nfunction tokenString(quote) {\n return function(stream, state) {\n var escaped = false, next, end = false;\n while((next = stream.next()) != null) {\n if (next == quote && !escaped) {\n end = true; break;\n }\n escaped = !escaped && next == \"\\\\\";\n }\n if (end || !escaped)\n state.tokenize = tokenBase;\n return \"error\";\n };\n}\n\n\nfunction tokenBase(stream, state) {\n var ch = stream.next();\n\n // is a start of string?\n if (ch == '\"' || ch == \"'\")\n return chain(stream, state, tokenString(ch));\n // is it one of the special chars\n else if(/[\\[\\]{}\\(\\),;\\.]/.test(ch))\n return null;\n // is it a number?\n else if(/\\d/.test(ch)) {\n stream.eatWhile(/[\\w\\.]/);\n return \"number\";\n }\n // multi line comment or operator\n else if (ch == \"/\") {\n if (stream.eat(\"*\")) {\n return chain(stream, state, tokenComment);\n }\n else {\n stream.eatWhile(isOperatorChar);\n return \"operator\";\n }\n }\n // single line comment or operator\n else if (ch==\"-\") {\n if(stream.eat(\"-\")){\n stream.skipToEnd();\n return \"comment\";\n }\n else {\n stream.eatWhile(isOperatorChar);\n return \"operator\";\n }\n }\n // is it an operator\n else if (isOperatorChar.test(ch)) {\n stream.eatWhile(isOperatorChar);\n return \"operator\";\n }\n else {\n // get the while word\n stream.eatWhile(/[\\w\\$_]/);\n // is it one of the listed keywords?\n if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) {\n //keywords can be used as variables like flatten(group), group.$0 etc..\n if (!stream.eat(\")\") && !stream.eat(\".\"))\n return \"keyword\";\n }\n // is it one of the builtin functions?\n if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase()))\n return \"builtin\";\n // is it one of the listed types?\n if (types && types.propertyIsEnumerable(stream.current().toUpperCase()))\n return \"type\";\n // default is a 'variable'\n return \"variable\";\n }\n}\n\n// Interface\nexport const pig = {\n name: \"pig\",\n\n startState: function() {\n return {\n tokenize: tokenBase,\n startOfLine: true\n };\n },\n\n token: function(stream, state) {\n if(stream.eatSpace()) return null;\n var style = state.tokenize(stream, state);\n return style;\n },\n\n languageData: {\n autocomplete: (pBuiltins + pTypes + pKeywords).split(\" \")\n }\n};\n"],"names":["words","str","obj","split","i","length","pBuiltins","pKeywords","pTypes","builtins","keywords","types","isOperatorChar","chain","stream","state","f","tokenize","tokenComment","ch","isEnd","next","tokenBase","quote","escaped","end","test","eatWhile","eat","skipToEnd","propertyIsEnumerable","current","toUpperCase","pig","name","startState","startOfLine","token","eatSpace","languageData","autocomplete"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/1711.index.js b/book/_build/html/_static/1711.index.js
new file mode 100644
index 0000000..28e7fc8
--- /dev/null
+++ b/book/_build/html/_static/1711.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[1711],{41711:(e,t,r)=>{r.r(t),r.d(t,{stylus:()=>oe});var i=["a","abbr","address","area","article","aside","audio","b","base","bdi","bdo","bgsound","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","div","dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","kbd","keygen","label","legend","li","link","main","map","mark","marquee","menu","menuitem","meta","meter","nav","nobr","noframes","noscript","object","ol","optgroup","option","output","p","param","pre","progress","q","rp","rt","ruby","s","samp","script","section","select","small","source","span","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","track","u","ul","var","video"],a=["domain","regexp","url-prefix","url"],o=["all","aural","braille","handheld","print","projection","screen","tty","tv","embossed"],n=["width","min-width","max-width","height","min-height","max-height","device-width","min-device-width","max-device-width","device-height","min-device-height","max-device-height","aspect-ratio","min-aspect-ratio","max-aspect-ratio","device-aspect-ratio","min-device-aspect-ratio","max-device-aspect-ratio","color","min-color","max-color","color-index","min-color-index","max-color-index","monochrome","min-monochrome","max-monochrome","resolution","min-resolution","max-resolution","scan","grid","dynamic-range","video-dynamic-range"],l=["align-content","align-items","align-self","alignment-adjust","alignment-baseline","anchor-point","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","azimuth","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","baseline-shift","binding","bleed","bookmark-label","bookmark-level","bookmark-state","bookmark-target","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","color","color-profile","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","crop","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","drop-initial-after-adjust","drop-initial-after-align","drop-initial-before-adjust","drop-initial-before-align","drop-initial-size","drop-initial-value","elevation","empty-cells","fit","fit-position","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","float-offset","flow-from","flow-into","font","font-feature-settings","font-family","font-kerning","font-language-override","font-size","font-size-adjust","font-stretch","font-style","font-synthesis","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-weight","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-position","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","inline-box-align","justify-content","left","letter-spacing","line-break","line-height","line-stacking","line-stacking-ruby","line-stacking-shift","line-stacking-strategy","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marker-offset","marks","marquee-direction","marquee-loop","marquee-play-count","marquee-speed","marquee-style","max-height","max-width","min-height","min-width","move-to","nav-down","nav-index","nav-left","nav-right","nav-up","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-style","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","page-policy","pause","pause-after","pause-before","perspective","perspective-origin","pitch","pitch-range","play-during","position","presentation-level","punctuation-trim","quotes","region-break-after","region-break-before","region-break-inside","region-fragment","rendering-intent","resize","rest","rest-after","rest-before","richness","right","rotation","rotation-point","ruby-align","ruby-overhang","ruby-position","ruby-span","shape-image-threshold","shape-inside","shape-margin","shape-outside","size","speak","speak-as","speak-header","speak-numeral","speak-punctuation","speech-rate","stress","string-set","tab-size","table-layout","target","target-name","target-new","target-position","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-height","text-indent","text-justify","text-outline","text-overflow","text-shadow","text-size-adjust","text-space-collapse","text-transform","text-underline-position","text-wrap","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","volume","white-space","widows","width","will-change","word-break","word-spacing","word-wrap","z-index","clip-path","clip-rule","mask","enable-background","filter","flood-color","flood-opacity","lighting-color","stop-color","stop-opacity","pointer-events","color-interpolation","color-interpolation-filters","color-rendering","fill","fill-opacity","fill-rule","image-rendering","marker","marker-end","marker-mid","marker-start","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-rendering","baseline-shift","dominant-baseline","glyph-orientation-horizontal","glyph-orientation-vertical","text-anchor","writing-mode","font-smoothing","osx-font-smoothing"],s=["scrollbar-arrow-color","scrollbar-base-color","scrollbar-dark-shadow-color","scrollbar-face-color","scrollbar-highlight-color","scrollbar-shadow-color","scrollbar-3d-light-color","scrollbar-track-color","shape-inside","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","zoom"],c=["font-family","src","unicode-range","font-variant","font-feature-settings","font-stretch","font-weight","font-style"],d=["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"],u=["above","absolute","activeborder","additive","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","attr","auto","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","bullets","button","buttonface","buttonhighlight","buttonshadow","buttontext","calc","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","column","compact","condensed","conic-gradient","contain","content","contents","content-box","context-menu","continuous","copy","counter","counters","cover","crop","cross","crosshair","currentcolor","cursive","cyclic","dashed","decimal","decimal-leading-zero","default","default-button","destination-atop","destination-in","destination-out","destination-over","devanagari","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ethiopic-numeric","ew-resize","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","flex","footnotes","forwards","from","geometricPrecision","georgian","graytext","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hebrew","help","hidden","hide","high","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-table","inset","inside","intrinsic","invert","italic","japanese-formal","japanese-informal","justify","kannada","katakana","katakana-iroha","keep-all","khmer","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","landscape","lao","large","larger","left","level","lighter","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","malayalam","match","matrix","matrix3d","media-play-button","media-slider","media-sliderthumb","media-volume-slider","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","octal","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","perspective","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeating-conic-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row-resize","rtl","run-in","running","s-resize","sans-serif","scale","scale3d","scaleX","scaleY","scaleZ","scroll","scrollbar","scroll-position","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","semi-condensed","semi-expanded","separate","serif","show","sidama","simp-chinese-formal","simp-chinese-informal","single","skew","skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","solid","somali","source-atop","source-in","source-out","source-over","space","spell-out","square","square-button","standard","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","symbolic","symbols","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","tamil","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","trad-chinese-formal","trad-chinese-informal","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","var","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","x-large","x-small","xor","xx-large","xx-small","bicubic","optimizespeed","grayscale","row","row-reverse","wrap","wrap-reverse","column-reverse","flex-start","flex-end","space-between","space-around","unset"],m=["in","and","or","not","is not","is a","is","isnt","defined","if unless"],p=["for","if","else","unless","from","to"],h=["null","true","false","href","title","type","not-allowed","readonly","disabled"],b=i.concat(a,o,n,l,s,d,u,c,m,p,h,["@font-face","@keyframes","@media","@viewport","@page","@host","@supports","@block","@css"]);function g(e){return e=e.sort((function(e,t){return t>e})),new RegExp("^(("+e.join(")|(")+"))\\b")}function f(e){for(var t={},r=0;r]=?|\?:|\~)/,E=g(m),O=f(p),W=new RegExp(/^\-(moz|ms|o|webkit)-/i),A=f(h),R="",S={};function X(e,t){if(R=e.string.match(/(^[\w-]+\s*=\s*$)|(^\s*[\w-]+\s*=\s*[\w-])|(^\s*(\.|#|@|\$|\&|\[|\d|\+|::?|\{|\>|~|\/)?\s*[\w-]*([a-z0-9-]|\*|\/\*)(\(|,)?)/),t.context.line.firstWord=R?R[0].replace(/^\s*/,""):"",t.context.line.indent=e.indentation(),k=e.peek(),e.match("//"))return e.skipToEnd(),["comment","comment"];if(e.match("/*"))return t.tokenize=Y,Y(e,t);if('"'==k||"'"==k)return e.next(),t.tokenize=Z(k),t.tokenize(e,t);if("@"==k)return e.next(),e.eatWhile(/[\w\\-]/),["def",e.current()];if("#"==k){if(e.next(),e.match(/^[0-9a-f]{3}([0-9a-f]([0-9a-f]{2}){0,2})?\b(?!-)/i))return["atom","atom"];if(e.match(/^[a-z][\w-]*/i))return["builtin","hash"]}return e.match(W)?["meta","vendor-prefixes"]:e.match(/^-?[0-9]?\.?[0-9]/)?(e.eatWhile(/[a-z%]/i),["number","unit"]):"!"==k?(e.next(),[e.match(/^(important|optional)/i)?"keyword":"operator","important"]):"."==k&&e.match(/^\.[a-z][\w-]*/i)?["qualifier","qualifier"]:e.match(N)?("("==e.peek()&&(t.tokenize=I),["property","word"]):e.match(/^[a-z][\w-]*\(/i)?(e.backUp(1),["keyword","mixin"]):e.match(/^(\+|-)[a-z][\w-]*\(/i)?(e.backUp(1),["keyword","block-mixin"]):e.string.match(/^\s*&/)&&e.match(/^[-_]+[a-z][\w-]*/)?["qualifier","qualifier"]:e.match(/^(\/|&)(-|_|:|\.|#|[a-z])/)?(e.backUp(1),["variableName.special","reference"]):e.match(/^&{1}\s*$/)?["variableName.special","reference"]:e.match(E)?["operator","operator"]:e.match(/^\$?[-_]*[a-z0-9]+[\w-]*/i)?e.match(/^(\.|\[)[\w-\'\"\]]+/i,!1)&&!H(e.current())?(e.match("."),["variable","variable-name"]):["variable","word"]:e.match(U)?["operator",e.current()]:/[:;,{}\[\]\(\)]/.test(k)?(e.next(),[null,k]):(e.next(),[null,null])}function Y(e,t){for(var r,i=!1;null!=(r=e.next());){if(i&&"/"==r){t.tokenize=null;break}i="*"==r}return["comment","comment"]}function Z(e){return function(t,r){for(var i,a=!1;null!=(i=t.next());){if(i==e&&!a){")"==e&&t.backUp(1);break}a=!a&&"\\"==i}return(i==e||!a&&")"!=e)&&(r.tokenize=null),["string","string"]}}function I(e,t){return e.next(),e.match(/\s*[\"\')]/,!1)?t.tokenize=null:t.tokenize=Z(")"),[null,"("]}function T(e,t,r,i){this.type=e,this.indent=t,this.prev=r,this.line=i||{firstWord:"",indent:0}}function D(e,t,r,i){return i=i>=0?i:t.indentUnit,e.context=new T(r,t.indentation()+i,e.context),r}function F(e,t,r){var i=e.context.indent-t.indentUnit;return r=r||!1,e.context=e.context.prev,r&&(e.context.indent=i),e.context.type}function G(e,t,r,i){for(var a=i||1;a>0;a--)r.context=r.context.prev;return function(e,t,r){return S[r.context.type](e,t,r)}(e,t,r)}function H(e){return e.toLowerCase()in x}function J(e){return(e=e.toLowerCase())in q||e in _}function K(e){return e.toLowerCase()in O}function M(e){return e.toLowerCase().match(W)}function Q(e){var t=e.toLowerCase(),r="variable";return H(e)?r="tag":K(e)?r="block-keyword":J(e)?r="property":t in j||t in A?r="atom":"return"==t||t in B?r="keyword":e.match(/^[A-Z]/)&&(r="string"),r}function V(e,t){return ie(t)&&("{"==e||"]"==e||"hash"==e||"qualifier"==e)||"block-mixin"==e}function ee(e,t){return"{"==e&&t.match(/^\s*\$?[\w-]+/i,!1)}function te(e,t){return":"==e&&t.match(/^[a-z-]+/,!1)}function re(e){return e.sol()||e.string.match(new RegExp("^\\s*"+e.current().replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")))}function ie(e){return e.eol()||e.match(/^\s*$/,!1)}function ae(e){var t=/^\s*[-_]*[a-z0-9]+[\w-]*/i,r="string"==typeof e?e.match(t):e.string.match(t);return r?r[0].replace(/^\s*/,""):""}S.block=function(e,t,r){if("comment"==e&&re(t)||","==e&&ie(t)||"mixin"==e)return D(r,t,"block",0);if(ee(e,t))return D(r,t,"interpolation");if(ie(t)&&"]"==e&&!/^\s*(\.|#|:|\[|\*|&)/.test(t.string)&&!H(ae(t)))return D(r,t,"block",0);if(V(e,t))return D(r,t,"block");if("}"==e&&ie(t))return D(r,t,"block",0);if("variable-name"==e)return t.string.match(/^\s?\$[\w-\.\[\]\'\"]+$/)||K(ae(t))?D(r,t,"variableName"):D(r,t,"variableName",0);if("="==e)return ie(t)||K(ae(t))?D(r,t,"block"):D(r,t,"block",0);if("*"==e&&(ie(t)||t.match(/\s*(,|\.|#|\[|:|{)/,!1)))return v="tag",D(r,t,"block");if(te(e,t))return D(r,t,"pseudo");if(/@(font-face|media|supports|(-moz-)?document)/.test(e))return D(r,t,ie(t)?"block":"atBlock");if(/@(-(moz|ms|o|webkit)-)?keyframes$/.test(e))return D(r,t,"keyframes");if(/@extends?/.test(e))return D(r,t,"extend",0);if(e&&"@"==e.charAt(0))return t.indentation()>0&&J(t.current().slice(1))?(v="variable","block"):/(@import|@require|@charset)/.test(e)?D(r,t,"block",0):D(r,t,"block");if("reference"==e&&ie(t))return D(r,t,"block");if("("==e)return D(r,t,"parens");if("vendor-prefixes"==e)return D(r,t,"vendorPrefixes");if("word"==e){var i=t.current();if("property"==(v=Q(i)))return re(t)?D(r,t,"block",0):(v="atom","block");if("tag"==v){if(/embed|menu|pre|progress|sub|table/.test(i)&&J(ae(t)))return v="atom","block";if(t.string.match(new RegExp("\\[\\s*"+i+"|"+i+"\\s*\\]")))return v="atom","block";if(z.test(i)&&(re(t)&&t.string.match(/=/)||!re(t)&&!t.string.match(/^(\s*\.|#|\&|\[|\/|>|\*)/)&&!H(ae(t))))return v="variable",K(ae(t))?"block":D(r,t,"block",0);if(ie(t))return D(r,t,"block")}if("block-keyword"==v)return v="keyword",t.current(/(if|unless)/)&&!re(t)?"block":D(r,t,"block");if("return"==i)return D(r,t,"block",0);if("variable"==v&&t.string.match(/^\s?\$[\w-\.\[\]\'\"]+$/))return D(r,t,"block")}return r.context.type},S.parens=function(e,t,r){if("("==e)return D(r,t,"parens");if(")"==e)return"parens"==r.context.prev.type?F(r,t):t.string.match(/^[a-z][\w-]*\(/i)&&ie(t)||K(ae(t))||/(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(ae(t))||!t.string.match(/^-?[a-z][\w-\.\[\]\'\"]*\s*=/)&&H(ae(t))?D(r,t,"block"):t.string.match(/^[\$-]?[a-z][\w-\.\[\]\'\"]*\s*=/)||t.string.match(/^\s*(\(|\)|[0-9])/)||t.string.match(/^\s+[a-z][\w-]*\(/i)||t.string.match(/^\s+[\$-]?[a-z]/i)?D(r,t,"block",0):ie(t)?D(r,t,"block"):D(r,t,"block",0);if(e&&"@"==e.charAt(0)&&J(t.current().slice(1))&&(v="variable"),"word"==e){var i=t.current();"tag"==(v=Q(i))&&z.test(i)&&(v="variable"),"property"!=v&&"to"!=i||(v="atom")}return"variable-name"==e?D(r,t,"variableName"):te(e,t)?D(r,t,"pseudo"):r.context.type},S.vendorPrefixes=function(e,t,r){return"word"==e?(v="property",D(r,t,"block",0)):F(r,t)},S.pseudo=function(e,t,r){return J(ae(t.string))?G(e,t,r):(t.match(/^[a-z-]+/),v="variableName.special",ie(t)?D(r,t,"block"):F(r,t))},S.atBlock=function(e,t,r){if("("==e)return D(r,t,"atBlock_parens");if(V(e,t))return D(r,t,"block");if(ee(e,t))return D(r,t,"interpolation");if("word"==e){var i=t.current().toLowerCase();if("tag"==(v=/^(only|not|and|or)$/.test(i)?"keyword":C.hasOwnProperty(i)?"tag":P.hasOwnProperty(i)?"attribute":L.hasOwnProperty(i)?"property":$.hasOwnProperty(i)?"string.special":Q(t.current()))&&ie(t))return D(r,t,"block")}return"operator"==e&&/^(not|and|or)$/.test(t.current())&&(v="keyword"),r.context.type},S.atBlock_parens=function(e,t,r){if("{"==e||"}"==e)return r.context.type;if(")"==e)return ie(t)?D(r,t,"block"):D(r,t,"atBlock");if("word"==e){var i=t.current().toLowerCase();return v=Q(i),/^(max|min)/.test(i)&&(v="property"),"tag"==v&&(v=z.test(i)?"variable":"atom"),r.context.type}return S.atBlock(e,t,r)},S.keyframes=function(e,t,r){return"0"==t.indentation()&&("}"==e&&re(t)||"]"==e||"hash"==e||"qualifier"==e||H(t.current()))?G(e,t,r):"{"==e?D(r,t,"keyframes"):"}"==e?re(t)?F(r,t,!0):D(r,t,"keyframes"):"unit"==e&&/^[0-9]+\%$/.test(t.current())?D(r,t,"keyframes"):"word"==e&&"block-keyword"==(v=Q(t.current()))?(v="keyword",D(r,t,"keyframes")):/@(font-face|media|supports|(-moz-)?document)/.test(e)?D(r,t,ie(t)?"block":"atBlock"):"mixin"==e?D(r,t,"block",0):r.context.type},S.interpolation=function(e,t,r){return"{"==e&&F(r,t)&&D(r,t,"block"),"}"==e?t.string.match(/^\s*(\.|#|:|\[|\*|&|>|~|\+|\/)/i)||t.string.match(/^\s*[a-z]/i)&&H(ae(t))?D(r,t,"block"):!t.string.match(/^(\{|\s*\&)/)||t.match(/\s*[\w-]/,!1)?D(r,t,"block",0):D(r,t,"block"):"variable-name"==e?D(r,t,"variableName",0):("word"==e&&"tag"==(v=Q(t.current()))&&(v="atom"),r.context.type)},S.extend=function(e,t,r){return"["==e||"="==e?"extend":"]"==e?F(r,t):"word"==e?(v=Q(t.current()),"extend"):F(r,t)},S.variableName=function(e,t,r){return"string"==e||"["==e||"]"==e||t.current().match(/^(\.|\$)/)?(t.current().match(/^\.[\w-]+/i)&&(v="variable"),"variableName"):G(e,t,r)};const oe={name:"stylus",startState:function(){return{tokenize:null,state:"block",context:new T("block",0,null)}},token:function(e,t){return!t.tokenize&&e.eatSpace()?null:((w=(t.tokenize||X)(e,t))&&"object"==typeof w&&(y=w[1],w=w[0]),v=w,t.state=S[t.state](y,e,t),v)},indent:function(e,t,r){var i=e.context,a=t&&t.charAt(0),o=i.indent,n=ae(t),l=r.lineIndent(r.pos),s=e.context.prev?e.context.prev.line.firstWord:"",c=e.context.prev?e.context.prev.line.indent:l;return i.prev&&("}"==a&&("block"==i.type||"atBlock"==i.type||"keyframes"==i.type)||")"==a&&("parens"==i.type||"atBlock_parens"==i.type)||"{"==a&&"at"==i.type)?o=i.indent-r.unit:/(\})/.test(a)||(/@|\$|\d/.test(a)||/^\{/.test(t)||/^\s*\/(\/|\*)/.test(t)||/^\s*\/\*/.test(s)||/^\s*[\w-\.\[\]\'\"]+\s*(\?|:|\+)?=/i.test(t)||/^(\+|-)?[a-z][\w-]*\(/i.test(t)||/^return/.test(t)||K(n)?o=l:/(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(a)||H(n)?o=/\,\s*$/.test(s)?c:e.sol()||!/(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(s)&&!H(s)?l:l<=c?c:c+r.unit:/,\s*$/.test(t)||!M(n)&&!J(n)||(o=K(s)?l<=c?c:c+r.unit:/^\{/.test(s)?l<=c?l:c+r.unit:M(s)||J(s)?l>=c?c:l:/^(\.|#|:|\[|\*|&|@|\+|\-|>|~|\/)/.test(s)||/=\s*$/.test(s)||H(s)||/^\$[\w-\.\[\]\'\"]/.test(s)?c+r.unit:l)),o},languageData:{indentOnInput:/^\s*\}$/,commentTokens:{line:"//",block:{open:"/*",close:"*/"}},autocomplete:b}}}}]);
+//# sourceMappingURL=1711.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/1711.index.js.map b/book/_build/html/_static/1711.index.js.map
new file mode 100644
index 0000000..376a48d
--- /dev/null
+++ b/book/_build/html/_static/1711.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"1711.index.js","mappings":"6HACA,IAAIA,EAAe,CAAC,IAAI,OAAO,UAAU,OAAO,UAAU,QAAQ,QAAS,IAAK,OAAO,MAAO,MAAM,UAAU,aAAa,OAAO,KAAK,SAAS,SAAS,UAAU,OAAQ,OAAO,MAAM,WAAW,OAAO,WAAW,KAAK,MAAM,UAAU,MAAM,MAAO,KAAK,KAAK,KAAK,QAAQ,WAAW,aAAa,SAAS,SAAS,OAAO,KAAM,KAAK,KAAK,KAAK,KAAK,KAAK,OAAO,SAAS,SAAS,KAAK,OAAO,IAAI,SAAU,MAAM,QAAQ,MAAM,MAAM,SAAS,QAAQ,SAAS,KAAK,OAAO,OAAO,MAAO,OAAO,UAAU,OAAO,WAAW,OAAO,QAAQ,MAAM,OAAO,WAAY,WAAW,SAAS,KAAK,WAAW,SAAS,SAAS,IAAI,QAAQ,MAAO,WAAW,IAAI,KAAK,KAAK,OAAO,IAAI,OAAO,SAAS,UAAU,SAAU,QAAQ,SAAS,OAAO,SAAS,QAAQ,MAAM,UAAU,MAAM,QAAQ,QAAQ,KAAK,WAAW,QAAQ,KAAK,QAAQ,OAAO,KAAK,QAAS,IAAI,KAAK,MAAM,SAI/0BC,EAAiB,CAAC,SAAU,SAAU,aAAc,OACpDC,EAAc,CAAC,MAAM,QAAQ,UAAU,WAAW,QAAQ,aAAa,SAAS,MAAM,KAAK,YAC3FC,EAAiB,CAAC,QAAQ,YAAY,YAAY,SAAS,aAAa,aAAa,eAAe,mBAAmB,mBAAmB,gBAAgB,oBAAoB,oBAAoB,eAAe,mBAAmB,mBAAmB,sBAAsB,0BAA0B,0BAA0B,QAAQ,YAAY,YAAY,cAAc,kBAAkB,kBAAkB,aAAa,iBAAiB,iBAAiB,aAAa,iBAAiB,iBAAiB,OAAO,OAAO,gBAAgB,uBAC/gBC,EAAoB,CAAC,gBAAgB,cAAc,aAAa,mBAAmB,qBAAqB,eAAe,YAAY,kBAAkB,sBAAsB,qBAAqB,sBAAsB,4BAA4B,iBAAiB,uBAAuB,4BAA4B,aAAa,UAAU,sBAAsB,aAAa,wBAAwB,kBAAkB,mBAAmB,mBAAmB,oBAAoB,sBAAsB,oBAAoB,kBAAkB,iBAAiB,UAAU,QAAQ,iBAAiB,iBAAiB,iBAAiB,kBAAkB,SAAS,gBAAgB,sBAAsB,4BAA4B,6BAA6B,sBAAsB,sBAAsB,kBAAkB,eAAe,eAAe,sBAAsB,sBAAsB,qBAAqB,sBAAsB,qBAAqB,cAAc,oBAAoB,oBAAoB,oBAAoB,gBAAgB,eAAe,qBAAqB,qBAAqB,qBAAqB,iBAAiB,eAAe,aAAa,mBAAmB,yBAAyB,0BAA0B,mBAAmB,mBAAmB,eAAe,SAAS,uBAAuB,aAAa,aAAa,cAAc,eAAe,eAAe,eAAe,QAAQ,OAAO,QAAQ,gBAAgB,eAAe,cAAc,aAAa,cAAc,oBAAoB,oBAAoB,oBAAoB,cAAc,eAAe,UAAU,UAAU,oBAAoB,gBAAgB,OAAO,MAAM,YAAY,aAAa,SAAS,YAAY,UAAU,oBAAoB,4BAA4B,2BAA2B,6BAA6B,4BAA4B,oBAAoB,qBAAqB,YAAY,cAAc,MAAM,eAAe,OAAO,aAAa,iBAAiB,YAAY,YAAY,cAAc,YAAY,QAAQ,eAAe,YAAY,YAAY,OAAO,wBAAwB,cAAc,eAAe,yBAAyB,YAAY,mBAAmB,eAAe,aAAa,iBAAiB,eAAe,0BAA0B,oBAAoB,0BAA0B,yBAAyB,uBAAuB,wBAAwB,cAAc,OAAO,YAAY,oBAAoB,iBAAiB,qBAAqB,iBAAiB,cAAc,kBAAkB,oBAAoB,WAAW,eAAe,iBAAiB,gBAAgB,sBAAsB,wBAAwB,qBAAqB,sBAAsB,SAAS,UAAU,OAAO,oBAAoB,kBAAkB,mBAAmB,mBAAmB,kBAAkB,OAAO,iBAAiB,aAAa,cAAc,gBAAgB,qBAAqB,sBAAsB,yBAAyB,aAAa,mBAAmB,sBAAsB,kBAAkB,SAAS,gBAAgB,cAAc,eAAe,aAAa,gBAAgB,QAAQ,oBAAoB,eAAe,qBAAqB,gBAAgB,gBAAgB,aAAa,YAAY,aAAa,YAAY,UAAU,WAAW,YAAY,WAAW,YAAY,SAAS,aAAa,kBAAkB,UAAU,QAAQ,UAAU,UAAU,gBAAgB,iBAAiB,gBAAgB,gBAAgB,WAAW,iBAAiB,gBAAgB,aAAa,aAAa,UAAU,iBAAiB,eAAe,gBAAgB,cAAc,OAAO,mBAAmB,oBAAoB,oBAAoB,cAAc,QAAQ,cAAc,eAAe,cAAc,qBAAqB,QAAQ,cAAc,cAAc,WAAW,qBAAqB,mBAAmB,SAAS,qBAAqB,sBAAsB,sBAAsB,kBAAkB,mBAAmB,SAAS,OAAO,aAAa,cAAc,WAAW,QAAQ,WAAW,iBAAiB,aAAa,gBAAgB,gBAAgB,YAAY,wBAAwB,eAAe,eAAe,gBAAgB,OAAO,QAAQ,WAAW,eAAe,gBAAgB,oBAAoB,cAAc,SAAS,aAAa,WAAW,eAAe,SAAS,cAAc,aAAa,kBAAkB,aAAa,kBAAkB,kBAAkB,wBAAwB,uBAAuB,uBAAuB,wBAAwB,gBAAgB,sBAAsB,yBAAyB,sBAAsB,cAAc,cAAc,eAAe,eAAe,gBAAgB,cAAc,mBAAmB,sBAAsB,iBAAiB,0BAA0B,YAAY,MAAM,YAAY,mBAAmB,kBAAkB,aAAa,mBAAmB,sBAAsB,sBAAsB,6BAA6B,eAAe,iBAAiB,aAAa,gBAAgB,iBAAiB,eAAe,cAAc,cAAc,aAAa,eAAe,eAAe,SAAS,cAAc,SAAS,QAAQ,cAAc,aAAa,eAAe,YAAY,UAAU,YAAY,YAAY,OAAO,oBAAoB,SAAS,cAAc,gBAAgB,iBAAiB,aAAa,eAAe,iBAAiB,sBAAsB,8BAA8B,kBAAkB,OAAO,eAAe,YAAY,kBAAkB,SAAS,aAAa,aAAa,eAAe,kBAAkB,SAAS,mBAAmB,oBAAoB,iBAAiB,kBAAkB,oBAAoB,iBAAiB,eAAe,iBAAiB,iBAAiB,oBAAoB,+BAA+B,6BAA6B,cAAc,eAAe,iBAAiB,sBACtrLC,EAA+B,CAAC,wBAAwB,uBAAuB,8BAA8B,uBAAuB,4BAA4B,yBAAyB,2BAA2B,wBAAwB,eAAe,4BAA4B,yBAAyB,6BAA6B,iCAAiC,QAC9WC,EAAkB,CAAC,cAAc,MAAM,gBAAgB,eAAe,wBAAwB,eAAe,cAAc,cAC3HC,EAAiB,CAAC,YAAY,eAAe,OAAO,aAAa,QAAQ,QAAQ,SAAS,QAAQ,iBAAiB,OAAO,aAAa,QAAQ,YAAY,YAAY,aAAa,YAAY,QAAQ,iBAAiB,WAAW,UAAU,OAAO,WAAW,WAAW,gBAAgB,WAAW,YAAY,YAAY,cAAc,iBAAiB,aAAa,aAAa,UAAU,aAAa,eAAe,gBAAgB,gBAAgB,gBAAgB,aAAa,WAAW,cAAc,UAAU,aAAa,YAAY,cAAc,cAAc,UAAU,YAAY,aAAa,OAAO,YAAY,OAAO,OAAO,QAAQ,cAAc,WAAW,UAAU,YAAY,SAAS,QAAQ,QAAQ,WAAW,gBAAgB,YAAY,eAAe,YAAY,aAAa,YAAY,uBAAuB,YAAY,aAAa,YAAY,cAAc,gBAAgB,eAAe,iBAAiB,iBAAiB,cAAc,OAAO,YAAY,QAAQ,UAAU,SAAS,mBAAmB,aAAa,eAAe,eAAe,iBAAiB,kBAAkB,oBAAoB,kBAAkB,kBAAkB,eAAe,YAAY,YAAY,WAAW,cAAc,OAAO,UAAU,QAAQ,YAAY,SAAS,YAAY,SAAS,gBAAgB,YAAY,gBAAgB,gBAAgB,aAAa,YAAY,OAAO,OAAO,OAAO,aAAa,SAAS,gBAAgB,MAAM,YAAY,YAAY,cAAc,SAAS,aAAa,WAAW,WAAW,SAAS,SAAS,UAAU,YAAY,YAAY,OAAO,cAAc,YAAY,MAAM,OAAO,UAAU,SAAS,YAAY,SAAS,QAAQ,QAAQ,aAAa,SAAS,eAC5pDC,EAAiB,CAAC,QAAQ,WAAW,eAAe,WAAW,gBAAgB,OAAO,oBAAoB,QAAQ,QAAQ,MAAM,aAAa,aAAa,YAAY,SAAS,UAAU,kBAAkB,cAAc,eAAe,eAAe,WAAW,YAAY,OAAO,OAAO,QAAQ,eAAe,aAAa,eAAe,aAAa,YAAY,WAAW,QAAQ,gBAAgB,SAAS,UAAU,QAAQ,QAAQ,aAAa,OAAO,SAAS,SAAS,aAAa,OAAO,SAAS,QAAQ,YAAY,aAAa,UAAU,SAAS,aAAa,kBAAkB,eAAe,aAAa,OAAO,YAAY,aAAa,sBAAsB,UAAU,cAAc,QAAQ,OAAO,SAAS,WAAW,SAAS,cAAc,qBAAqB,oBAAoB,kBAAkB,QAAQ,OAAO,cAAc,aAAa,WAAW,SAAS,UAAU,YAAY,iBAAiB,UAAU,UAAU,WAAW,cAAc,eAAe,aAAa,OAAO,UAAU,WAAW,QAAQ,OAAO,QAAQ,YAAY,eAAe,UAAU,SAAS,SAAS,UAAU,uBAAuB,UAAU,iBAAiB,mBAAmB,iBAAiB,kBAAkB,mBAAmB,aAAa,OAAO,UAAU,oBAAoB,kBAAkB,WAAW,WAAW,eAAe,SAAS,SAAS,OAAO,WAAW,OAAO,UAAU,cAAc,WAAW,UAAU,UAAU,WAAW,QAAQ,MAAM,WAAW,mBAAmB,yBAAyB,uBAAuB,yBAAyB,yBAAyB,0BAA0B,0BAA0B,0BAA0B,wBAAwB,0BAA0B,2BAA2B,0BAA0B,0BAA0B,0BAA0B,wBAAwB,mBAAmB,YAAY,WAAW,UAAU,kBAAkB,iBAAiB,UAAU,OAAO,OAAO,QAAQ,OAAO,OAAO,YAAY,WAAW,OAAO,qBAAqB,WAAW,WAAW,SAAS,WAAW,WAAW,OAAO,SAAS,mBAAmB,SAAS,OAAO,SAAS,OAAO,OAAO,SAAS,YAAY,gBAAgB,WAAW,iBAAiB,aAAa,MAAM,OAAO,OAAO,SAAS,iBAAiB,kBAAkB,sBAAsB,WAAW,iBAAiB,WAAW,UAAU,UAAU,SAAS,cAAc,eAAe,cAAc,eAAe,QAAQ,SAAS,YAAY,SAAS,SAAS,kBAAkB,oBAAoB,UAAU,UAAU,WAAW,iBAAiB,WAAW,QAAQ,uBAAuB,sBAAsB,wBAAwB,YAAY,MAAM,QAAQ,SAAS,OAAO,QAAQ,UAAU,eAAe,SAAS,kBAAkB,QAAQ,YAAY,UAAU,WAAW,QAAQ,UAAU,OAAO,QAAQ,cAAc,iBAAiB,cAAc,oBAAoB,cAAc,kBAAkB,cAAc,YAAY,MAAM,YAAY,QAAQ,SAAS,WAAW,oBAAoB,eAAe,oBAAoB,sBAAsB,2BAA2B,SAAS,OAAO,WAAW,kBAAkB,WAAW,cAAc,SAAS,gBAAgB,MAAM,YAAY,YAAY,OAAO,WAAW,UAAU,WAAW,WAAW,YAAY,cAAc,iBAAiB,UAAU,gBAAgB,YAAY,OAAO,SAAS,cAAc,SAAS,YAAY,UAAU,UAAU,YAAY,cAAc,UAAU,QAAQ,aAAa,qBAAqB,gBAAgB,QAAQ,QAAQ,SAAS,UAAU,gBAAgB,UAAU,WAAW,UAAU,cAAc,UAAU,OAAO,SAAS,UAAU,cAAc,cAAc,eAAe,UAAU,UAAU,WAAW,MAAM,WAAW,WAAW,cAAc,WAAW,cAAc,kBAAkB,QAAQ,YAAY,aAAa,4BAA4B,YAAY,SAAS,WAAW,SAAS,4BAA4B,4BAA4B,2BAA2B,WAAW,WAAW,QAAQ,UAAU,MAAM,OAAO,QAAQ,QAAQ,SAAS,WAAW,UAAU,UAAU,UAAU,QAAQ,aAAa,MAAM,SAAS,UAAU,WAAW,aAAa,QAAQ,UAAU,SAAS,SAAS,SAAS,SAAS,YAAY,kBAAkB,YAAY,cAAc,4BAA4B,yBAAyB,6BAA6B,iCAAiC,iBAAiB,gBAAgB,WAAW,QAAQ,OAAO,SAAS,sBAAsB,wBAAwB,SAAS,OAAO,QAAQ,QAAQ,mBAAmB,QAAQ,oBAAoB,kBAAkB,yBAAyB,uBAAuB,OAAO,QAAQ,aAAa,gBAAgB,UAAU,QAAQ,SAAS,cAAc,YAAY,aAAa,cAAc,QAAQ,YAAY,SAAS,gBAAgB,WAAW,QAAQ,SAAS,aAAa,UAAU,SAAS,MAAM,uBAAuB,QAAQ,YAAY,WAAW,UAAU,QAAQ,gBAAgB,aAAa,eAAe,qBAAqB,qBAAqB,qBAAqB,YAAY,kBAAkB,QAAQ,SAAS,OAAO,cAAc,WAAW,WAAW,YAAY,OAAO,QAAQ,OAAO,mBAAmB,aAAa,kBAAkB,oBAAoB,eAAe,UAAU,QAAQ,cAAc,sBAAsB,cAAc,sBAAsB,KAAK,MAAM,sBAAsB,wBAAwB,YAAY,cAAc,aAAa,aAAa,aAAa,cAAc,kBAAkB,iBAAiB,YAAY,KAAK,cAAc,iBAAiB,cAAc,oBAAoB,cAAc,kBAAkB,cAAc,YAAY,OAAO,MAAM,MAAM,WAAW,gBAAgB,UAAU,cAAc,iBAAiB,gBAAgB,SAAS,WAAW,OAAO,OAAO,QAAQ,SAAS,cAAc,aAAa,QAAQ,UAAU,UAAU,MAAM,WAAW,WAAW,UAAU,gBAAgB,YAAY,MAAM,cAAc,OAAO,eAAe,iBAAiB,aAAa,WAAW,gBAAgB,eAAgB,SAEp8LC,EAAwB,CAAC,KAAK,MAAM,KAAK,MAAM,SAAS,OAAO,KAAK,OAAO,UAAU,aACrFC,EAAiB,CAAC,MAAM,KAAK,OAAO,SAAU,OAAQ,MACtDC,EAAe,CAAC,OAAO,OAAO,QAAQ,OAAO,QAAQ,OAAO,cAAc,WAAW,YAGrFC,EAAYZ,EAAaa,OAAOZ,EAAeC,EAAYC,EAC3BC,EAAkBC,EAClBE,EAAeC,EAAeF,EAC9BG,EAAsBC,EACtBC,EANnB,CAAC,aAAc,aAAc,SAAU,YAAa,QAAS,QAAS,YAAa,SAAU,SAQ9G,SAASG,EAAWC,GAElB,OADAA,EAAQA,EAAMC,MAAK,SAASC,EAAEC,GAAG,OAAOA,EAAID,CAAE,IACvC,IAAIE,OAAO,MAAQJ,EAAMK,KAAK,OAAS,QAChD,CAEA,SAASC,EAAOC,GAEd,IADA,IAAIC,EAAO,CAAC,EACHC,EAAI,EAAGA,EAAIF,EAAMG,SAAUD,EAAGD,EAAKD,EAAME,KAAM,EACxD,OAAOD,CACT,CAMA,IAkBIG,EACAC,EACAC,EACAC,EArBAC,EAAcT,EAAOrB,GACrB+B,EAAqB,sBACrBC,EAAmBX,EAAOjB,GAC1B6B,EAA8BZ,EAAOhB,GACrC6B,EAAgBb,EAAOb,GACvB2B,EAAgBd,EAAOd,GACvB6B,EAAgBf,EAAOpB,GACvBoC,EAAsBvB,EAAWb,GACjCqC,EAAgBjB,EAAOlB,GACvBoC,EAAalB,EAAOnB,GACpBsC,EAAiBnB,EAAOf,GACxBmC,EAAkB,2DAClBC,EAA6B5B,EAAWL,GACxCkC,EAAgBtB,EAAOX,GACvBkC,EAAuB,IAAIzB,OAAO,0BAClC0B,EAAcxB,EAAOV,GACrBmC,EAAiB,GACjBC,EAAS,CAAC,EASd,SAASC,EAAUC,EAAQC,GAOzB,GANAJ,EAAiBG,EAAOE,OAAOC,MAAM,+HACrCF,EAAMG,QAAQC,KAAKC,UAAYT,EAAiBA,EAAe,GAAGU,QAAQ,OAAQ,IAAM,GACxFN,EAAMG,QAAQC,KAAKG,OAASR,EAAOS,cACnChC,EAAKuB,EAAOU,OAGRV,EAAOG,MAAM,MAEf,OADAH,EAAOW,YACA,CAAC,UAAW,WAGrB,GAAIX,EAAOG,MAAM,MAEf,OADAF,EAAMW,SAAWC,EACVA,EAAcb,EAAQC,GAG/B,GAAU,KAANxB,GAAoB,KAANA,EAGhB,OAFAuB,EAAOc,OACPb,EAAMW,SAAWG,EAAYtC,GACtBwB,EAAMW,SAASZ,EAAQC,GAGhC,GAAU,KAANxB,EAGF,OAFAuB,EAAOc,OACPd,EAAOgB,SAAS,WACT,CAAC,MAAOhB,EAAOiB,WAGxB,GAAU,KAANxC,EAAW,CAGb,GAFAuB,EAAOc,OAEHd,EAAOG,MAAM,qDACf,MAAO,CAAC,OAAQ,QAGlB,GAAIH,EAAOG,MAAM,iBACf,MAAO,CAAC,UAAW,OAEvB,CAEA,OAAIH,EAAOG,MAAMR,GACR,CAAC,OAAQ,mBAGdK,EAAOG,MAAM,sBACfH,EAAOgB,SAAS,WACT,CAAC,SAAU,SAGV,KAANvC,GACFuB,EAAOc,OACA,CAACd,EAAOG,MAAM,0BAA4B,UAAW,WAAY,cAGhE,KAAN1B,GAAauB,EAAOG,MAAM,mBACrB,CAAC,YAAa,aAGnBH,EAAOG,MAAMf,IACM,KAAjBY,EAAOU,SAAeT,EAAMW,SAAWM,GACpC,CAAC,WAAY,SAGlBlB,EAAOG,MAAM,oBACfH,EAAOmB,OAAO,GACP,CAAC,UAAW,UAGjBnB,EAAOG,MAAM,0BACfH,EAAOmB,OAAO,GACP,CAAC,UAAW,gBAGjBnB,EAAOE,OAAOC,MAAM,UAAYH,EAAOG,MAAM,qBACxC,CAAC,YAAa,aAGnBH,EAAOG,MAAM,8BACfH,EAAOmB,OAAO,GACP,CAAC,uBAAwB,cAE9BnB,EAAOG,MAAM,aACR,CAAC,uBAAwB,aAG9BH,EAAOG,MAAMV,GACR,CAAC,WAAY,YAGlBO,EAAOG,MAAM,6BAEXH,EAAOG,MAAM,yBAAyB,KACnCiB,EAAUpB,EAAOiB,YACpBjB,EAAOG,MAAM,KACN,CAAC,WAAY,kBAGjB,CAAC,WAAY,QAGlBH,EAAOG,MAAMX,GACR,CAAC,WAAYQ,EAAOiB,WAGzB,kBAAkBI,KAAK5C,IACzBuB,EAAOc,OACA,CAAC,KAAMrC,KAGhBuB,EAAOc,OACA,CAAC,KAAM,MAChB,CAKA,SAASD,EAAcb,EAAQC,GAE7B,IADA,IAAsBxB,EAAlB6C,GAAW,EACgB,OAAvB7C,EAAKuB,EAAOc,SAAiB,CACnC,GAAIQ,GAAkB,KAAN7C,EAAW,CACzBwB,EAAMW,SAAW,KACjB,KACF,CACAU,EAAkB,KAAN7C,CACd,CACA,MAAO,CAAC,UAAW,UACrB,CAKA,SAASsC,EAAYQ,GACnB,OAAO,SAASvB,EAAQC,GAEtB,IADA,IAAqBxB,EAAjB+C,GAAU,EACiB,OAAvB/C,EAAKuB,EAAOc,SAAiB,CACnC,GAAIrC,GAAM8C,IAAUC,EAAS,CACd,KAATD,GAAcvB,EAAOmB,OAAO,GAChC,KACF,CACAK,GAAWA,GAAiB,MAAN/C,CACxB,CAEA,OADIA,GAAM8C,IAAUC,GAAoB,KAATD,KAActB,EAAMW,SAAW,MACvD,CAAC,SAAU,SACpB,CACF,CAKA,SAASM,EAAmBlB,EAAQC,GAMlC,OALAD,EAAOc,OACFd,EAAOG,MAAM,cAAc,GAG9BF,EAAMW,SAAW,KAFjBX,EAAMW,SAAWG,EAAY,KAGxB,CAAC,KAAM,IAChB,CAKA,SAASU,EAAQ9C,EAAM6B,EAAQkB,EAAMrB,GACnCsB,KAAKhD,KAAOA,EACZgD,KAAKnB,OAASA,EACdmB,KAAKD,KAAOA,EACZC,KAAKtB,KAAOA,GAAQ,CAACC,UAAW,GAAIE,OAAQ,EAC9C,CAEA,SAASoB,EAAY3B,EAAOD,EAAQrB,EAAM6B,GAGxC,OAFAA,EAASA,GAAU,EAAIA,EAASR,EAAO6B,WACvC5B,EAAMG,QAAU,IAAIqB,EAAQ9C,EAAMqB,EAAOS,cAAgBD,EAAQP,EAAMG,SAChEzB,CACT,CAEA,SAASmD,EAAW7B,EAAOD,EAAQ+B,GACjC,IAAIC,EAAgB/B,EAAMG,QAAQI,OAASR,EAAO6B,WAIlD,OAHAE,EAAgBA,IAAiB,EACjC9B,EAAMG,QAAUH,EAAMG,QAAQsB,KAC1BK,IAAe9B,EAAMG,QAAQI,OAASwB,GACnC/B,EAAMG,QAAQzB,IACvB,CAMA,SAASsD,EAAWtD,EAAMqB,EAAQC,EAAOiC,GACvC,IAAK,IAAI3D,EAAI2D,GAAK,EAAG3D,EAAI,EAAGA,IAC1B0B,EAAMG,QAAUH,EAAMG,QAAQsB,KAChC,OAPF,SAAc/C,EAAMqB,EAAQC,GAC1B,OAAOH,EAAOG,EAAMG,QAAQzB,MAAMA,EAAMqB,EAAQC,EAClD,CAKSkC,CAAKxD,EAAMqB,EAAQC,EAC5B,CAMA,SAASmB,EAAUgB,GACjB,OAAOA,EAAKC,gBAAiBxD,CAC/B,CAEA,SAASyD,EAAeF,GAEtB,OADAA,EAAOA,EAAKC,iBACGtD,GAAoBqD,KAAQ7C,CAC7C,CAEA,SAASgD,EAAYH,GACnB,OAAOA,EAAKC,gBAAiB3C,CAC/B,CAEA,SAAS8C,EAAmBJ,GAC1B,OAAOA,EAAKC,cAAclC,MAAMR,EAClC,CAEA,SAAS8C,EAAYL,GACnB,IAAIM,EAASN,EAAKC,cACdzD,EAAW,WASf,OARIwC,EAAUgB,GAAOxD,EAAW,MACvB2D,EAAYH,GAAOxD,EAAW,gBAC9B0D,EAAeF,GAAOxD,EAAW,WACjC8D,KAAUzD,GAAiByD,KAAU9C,EAAahB,EAAW,OACnD,UAAV8D,GAAsBA,KAAUxD,EAAeN,EAAW,UAG1DwD,EAAKjC,MAAM,YAAWvB,EAAW,UACnCA,CACT,CAEA,SAAS+D,EAAYhE,EAAMqB,GACzB,OAAS4C,GAAU5C,KAAoB,KAARrB,GAAuB,KAARA,GAAuB,QAARA,GAA0B,aAARA,IAAiC,eAARA,CAC1G,CAEA,SAASkE,GAAoBlE,EAAMqB,GACjC,MAAe,KAARrB,GAAeqB,EAAOG,MAAM,kBAAkB,EACvD,CAEA,SAAS2C,GAAanE,EAAMqB,GAC1B,MAAe,KAARrB,GAAeqB,EAAOG,MAAM,YAAY,EACjD,CAEA,SAAS4C,GAAY/C,GACnB,OAAOA,EAAOgD,OAAShD,EAAOE,OAAOC,MAAM,IAAIjC,OAAO,QAAuB8B,EAAOiB,UA9QxEV,QAAQ,2BAA4B,SA+QlD,CAEA,SAASqC,GAAU5C,GACjB,OAAOA,EAAOiD,OAASjD,EAAOG,MAAM,SAAS,EAC/C,CAEA,SAAS+C,GAAgB7C,GACvB,IAAI8C,EAAK,4BACLC,EAAwB,iBAAR/C,EAAmBA,EAAKF,MAAMgD,GAAM9C,EAAKH,OAAOC,MAAMgD,GAC1E,OAAOC,EAASA,EAAO,GAAG7C,QAAQ,OAAQ,IAAM,EAClD,CAMAT,EAAOuD,MAAQ,SAAS1E,EAAMqB,EAAQC,GACpC,GAAa,WAARtB,GAAqBoE,GAAY/C,IACzB,KAARrB,GAAeiE,GAAU5C,IAClB,SAARrB,EACF,OAAOiD,EAAY3B,EAAOD,EAAQ,QAAS,GAE7C,GAAI6C,GAAoBlE,EAAMqB,GAC5B,OAAO4B,EAAY3B,EAAOD,EAAQ,iBAEpC,GAAI4C,GAAU5C,IAAmB,KAARrB,IAClB,uBAAuB0C,KAAKrB,EAAOE,UAAYkB,EAAU8B,GAAgBlD,IAC5E,OAAO4B,EAAY3B,EAAOD,EAAQ,QAAS,GAG/C,GAAI2C,EAAYhE,EAAMqB,GACpB,OAAO4B,EAAY3B,EAAOD,EAAQ,SAEpC,GAAY,KAARrB,GAAeiE,GAAU5C,GAC3B,OAAO4B,EAAY3B,EAAOD,EAAQ,QAAS,GAE7C,GAAY,iBAARrB,EACF,OAAIqB,EAAOE,OAAOC,MAAM,4BAA8BoC,EAAYW,GAAgBlD,IACzE4B,EAAY3B,EAAOD,EAAQ,gBAG3B4B,EAAY3B,EAAOD,EAAQ,eAAgB,GAGtD,GAAY,KAARrB,EACF,OAAKiE,GAAU5C,IAAYuC,EAAYW,GAAgBlD,IAGhD4B,EAAY3B,EAAOD,EAAQ,SAFzB4B,EAAY3B,EAAOD,EAAQ,QAAS,GAI/C,GAAY,KAARrB,IACEiE,GAAU5C,IAAWA,EAAOG,MAAM,sBAAqB,IAEzD,OADAvB,EAAW,MACJgD,EAAY3B,EAAOD,EAAQ,SAGtC,GAAI8C,GAAanE,EAAMqB,GACrB,OAAO4B,EAAY3B,EAAOD,EAAQ,UAEpC,GAAI,+CAA+CqB,KAAK1C,GACtD,OAAOiD,EAAY3B,EAAOD,EAAQ4C,GAAU5C,GAAU,QAAU,WAElE,GAAI,oCAAoCqB,KAAK1C,GAC3C,OAAOiD,EAAY3B,EAAOD,EAAQ,aAEpC,GAAI,YAAYqB,KAAK1C,GACnB,OAAOiD,EAAY3B,EAAOD,EAAQ,SAAU,GAE9C,GAAIrB,GAA0B,KAAlBA,EAAK2E,OAAO,GAGtB,OAAItD,EAAOS,cAAgB,GAAK6B,EAAetC,EAAOiB,UAAUsC,MAAM,KACpE3E,EAAW,WACJ,SAEL,8BAA8ByC,KAAK1C,GAC9BiD,EAAY3B,EAAOD,EAAQ,QAAS,GAEtC4B,EAAY3B,EAAOD,EAAQ,SAEpC,GAAY,aAARrB,GAAuBiE,GAAU5C,GACnC,OAAO4B,EAAY3B,EAAOD,EAAQ,SAEpC,GAAY,KAARrB,EACF,OAAOiD,EAAY3B,EAAOD,EAAQ,UAGpC,GAAY,mBAARrB,EACF,OAAOiD,EAAY3B,EAAOD,EAAQ,kBAEpC,GAAY,QAARrB,EAAgB,CAClB,IAAIyD,EAAOpC,EAAOiB,UAGlB,GAAgB,aAFhBrC,EAAW6D,EAAYL,IAGrB,OAAIW,GAAY/C,GACP4B,EAAY3B,EAAOD,EAAQ,QAAS,IAE3CpB,EAAW,OACJ,SAIX,GAAgB,OAAZA,EAAmB,CAGrB,GAAI,oCAAoCyC,KAAKe,IACvCE,EAAeY,GAAgBlD,IAEjC,OADApB,EAAW,OACJ,QAKX,GAAIoB,EAAOE,OAAOC,MAAM,IAAIjC,OAAO,UAAYkE,EAAO,IAAMA,EAAM,YAEhE,OADAxD,EAAW,OACJ,QAIT,GAAIE,EAAmBuC,KAAKe,KACrBW,GAAY/C,IAAWA,EAAOE,OAAOC,MAAM,OAC1C4C,GAAY/C,KACZA,EAAOE,OAAOC,MAAM,8BACpBiB,EAAU8B,GAAgBlD,KAE9B,OADApB,EAAW,WACP2D,EAAYW,GAAgBlD,IAAkB,QAC3C4B,EAAY3B,EAAOD,EAAQ,QAAS,GAI/C,GAAI4C,GAAU5C,GAAS,OAAO4B,EAAY3B,EAAOD,EAAQ,QAC3D,CACA,GAAgB,iBAAZpB,EAIF,OAHAA,EAAW,UAGPoB,EAAOiB,QAAQ,iBAAmB8B,GAAY/C,GACzC,QAEF4B,EAAY3B,EAAOD,EAAQ,SAEpC,GAAY,UAARoC,EAAkB,OAAOR,EAAY3B,EAAOD,EAAQ,QAAS,GAGjE,GAAgB,YAAZpB,GAA0BoB,EAAOE,OAAOC,MAAM,2BAChD,OAAOyB,EAAY3B,EAAOD,EAAQ,QAEtC,CACA,OAAOC,EAAMG,QAAQzB,IACvB,EAMAmB,EAAO0D,OAAS,SAAS7E,EAAMqB,EAAQC,GACrC,GAAY,KAARtB,EAAa,OAAOiD,EAAY3B,EAAOD,EAAQ,UACnD,GAAY,KAARrB,EACF,MAA+B,UAA3BsB,EAAMG,QAAQsB,KAAK/C,KACdmD,EAAW7B,EAAOD,GAEtBA,EAAOE,OAAOC,MAAM,oBAAsByC,GAAU5C,IACrDuC,EAAYW,GAAgBlD,KAC5B,6BAA6BqB,KAAK6B,GAAgBlD,MAChDA,EAAOE,OAAOC,MAAM,iCACrBiB,EAAU8B,GAAgBlD,IACtB4B,EAAY3B,EAAOD,EAAQ,SAEhCA,EAAOE,OAAOC,MAAM,qCACpBH,EAAOE,OAAOC,MAAM,sBACpBH,EAAOE,OAAOC,MAAM,uBACpBH,EAAOE,OAAOC,MAAM,oBACfyB,EAAY3B,EAAOD,EAAQ,QAAS,GAEzC4C,GAAU5C,GAAgB4B,EAAY3B,EAAOD,EAAQ,SAC7C4B,EAAY3B,EAAOD,EAAQ,QAAS,GAKlD,GAHIrB,GAA0B,KAAlBA,EAAK2E,OAAO,IAAahB,EAAetC,EAAOiB,UAAUsC,MAAM,MACzE3E,EAAW,YAED,QAARD,EAAgB,CAClB,IAAIyD,EAAOpC,EAAOiB,UAEF,QADhBrC,EAAW6D,EAAYL,KACEtD,EAAmBuC,KAAKe,KAC/CxD,EAAW,YAEG,YAAZA,GAAkC,MAARwD,IAAcxD,EAAW,OACzD,CACA,MAAY,iBAARD,EACKiD,EAAY3B,EAAOD,EAAQ,gBAEhC8C,GAAanE,EAAMqB,GACd4B,EAAY3B,EAAOD,EAAQ,UAE7BC,EAAMG,QAAQzB,IACvB,EAMAmB,EAAO2D,eAAiB,SAAS9E,EAAMqB,EAAQC,GAC7C,MAAY,QAARtB,GACFC,EAAW,WACJgD,EAAY3B,EAAOD,EAAQ,QAAS,IAEtC8B,EAAW7B,EAAOD,EAC3B,EAMAF,EAAO4D,OAAS,SAAS/E,EAAMqB,EAAQC,GACrC,OAAKqC,EAAeY,GAAgBlD,EAAOE,SAMpC+B,EAAWtD,EAAMqB,EAAQC,IAL9BD,EAAOG,MAAM,YACbvB,EAAW,uBACPgE,GAAU5C,GAAgB4B,EAAY3B,EAAOD,EAAQ,SAClD8B,EAAW7B,EAAOD,GAG7B,EAMAF,EAAO6D,QAAU,SAAShF,EAAMqB,EAAQC,GACtC,GAAY,KAARtB,EAAa,OAAOiD,EAAY3B,EAAOD,EAAQ,kBACnD,GAAI2C,EAAYhE,EAAMqB,GACpB,OAAO4B,EAAY3B,EAAOD,EAAQ,SAEpC,GAAI6C,GAAoBlE,EAAMqB,GAC5B,OAAO4B,EAAY3B,EAAOD,EAAQ,iBAEpC,GAAY,QAARrB,EAAgB,CAClB,IAAIyD,EAAOpC,EAAOiB,UAAUoB,cAY5B,GAAgB,QAVdzD,EADE,sBAAsByC,KAAKe,GAClB,UACJjD,EAAcyE,eAAexB,GACzB,MACJ9C,EAAWsE,eAAexB,GACtB,YACJ/C,EAAcuE,eAAexB,GACzB,WACJpD,EAA4B4E,eAAexB,GACvC,iBACGK,EAAYzC,EAAOiB,aACV2B,GAAU5C,GACjC,OAAO4B,EAAY3B,EAAOD,EAAQ,QAEtC,CAIA,MAHY,YAARrB,GAAsB,iBAAiB0C,KAAKrB,EAAOiB,aACrDrC,EAAW,WAENqB,EAAMG,QAAQzB,IACvB,EAEAmB,EAAO+D,eAAiB,SAASlF,EAAMqB,EAAQC,GAC7C,GAAY,KAARtB,GAAuB,KAARA,EAAa,OAAOsB,EAAMG,QAAQzB,KACrD,GAAY,KAARA,EACF,OAAIiE,GAAU5C,GAAgB4B,EAAY3B,EAAOD,EAAQ,SAC7C4B,EAAY3B,EAAOD,EAAQ,WAEzC,GAAY,QAARrB,EAAgB,CAClB,IAAIyD,EAAOpC,EAAOiB,UAAUoB,cAM5B,OALAzD,EAAW6D,EAAYL,GACnB,aAAaf,KAAKe,KAAOxD,EAAW,YACxB,OAAZA,IAC8BA,EAAhCE,EAAmBuC,KAAKe,GAAmB,WAAwB,QAE9DnC,EAAMG,QAAQzB,IACvB,CACA,OAAOmB,EAAO6D,QAAQhF,EAAMqB,EAAQC,EACtC,EAMAH,EAAOgE,UAAY,SAASnF,EAAMqB,EAAQC,GACxC,MAA4B,KAAxBD,EAAOS,gBAAkC,KAAR9B,GAAeoE,GAAY/C,IAAoB,KAARrB,GAAuB,QAARA,GAC5C,aAARA,GAAuByC,EAAUpB,EAAOiB,YACtEgB,EAAWtD,EAAMqB,EAAQC,GAEtB,KAARtB,EAAoBiD,EAAY3B,EAAOD,EAAQ,aACvC,KAARrB,EACEoE,GAAY/C,GAAgB8B,EAAW7B,EAAOD,GAAQ,GAC9C4B,EAAY3B,EAAOD,EAAQ,aAE7B,QAARrB,GAAkB,aAAa0C,KAAKrB,EAAOiB,WACtCW,EAAY3B,EAAOD,EAAQ,aAExB,QAARrB,GAEc,kBADhBC,EAAW6D,EAAYzC,EAAOiB,aAE5BrC,EAAW,UACJgD,EAAY3B,EAAOD,EAAQ,cAGlC,+CAA+CqB,KAAK1C,GAC/CiD,EAAY3B,EAAOD,EAAQ4C,GAAU5C,GAAU,QAAU,WAEtD,SAARrB,EACKiD,EAAY3B,EAAOD,EAAQ,QAAS,GAEtCC,EAAMG,QAAQzB,IACvB,EAMAmB,EAAOiE,cAAgB,SAASpF,EAAMqB,EAAQC,GAE5C,MADY,KAARtB,GAAamD,EAAW7B,EAAOD,IAAW4B,EAAY3B,EAAOD,EAAQ,SAC7D,KAARrB,EACEqB,EAAOE,OAAOC,MAAM,oCACnBH,EAAOE,OAAOC,MAAM,eAAiBiB,EAAU8B,GAAgBlD,IAC3D4B,EAAY3B,EAAOD,EAAQ,UAE/BA,EAAOE,OAAOC,MAAM,gBACrBH,EAAOG,MAAM,YAAW,GACnByB,EAAY3B,EAAOD,EAAQ,QAAS,GAEtC4B,EAAY3B,EAAOD,EAAQ,SAExB,iBAARrB,EACKiD,EAAY3B,EAAOD,EAAQ,eAAgB,IAExC,QAARrB,GAEc,QADhBC,EAAW6D,EAAYzC,EAAOiB,cACPrC,EAAW,QAE7BqB,EAAMG,QAAQzB,KACvB,EAMAmB,EAAOkE,OAAS,SAASrF,EAAMqB,EAAQC,GACrC,MAAY,KAARtB,GAAuB,KAARA,EAAoB,SAC3B,KAARA,EAAoBmD,EAAW7B,EAAOD,GAC9B,QAARrB,GACFC,EAAW6D,EAAYzC,EAAOiB,WACvB,UAEFa,EAAW7B,EAAOD,EAC3B,EAMAF,EAAOmE,aAAe,SAAStF,EAAMqB,EAAQC,GAC3C,MAAY,UAARtB,GAA4B,KAARA,GAAuB,KAARA,GAAeqB,EAAOiB,UAAUd,MAAM,aACvEH,EAAOiB,UAAUd,MAAM,gBAAevB,EAAW,YAC9C,gBAEFqD,EAAWtD,EAAMqB,EAAQC,EAClC,EAEO,MAAMiE,GAAS,CACpBC,KAAM,SACNC,WAAY,WACV,MAAO,CACLxD,SAAU,KACVX,MAAO,QACPG,QAAS,IAAIqB,EAAQ,QAAS,EAAG,MAErC,EACA4C,MAAO,SAASrE,EAAQC,GACtB,OAAKA,EAAMW,UAAYZ,EAAOsE,WAAmB,OACjD5F,GAASuB,EAAMW,UAAYb,GAAWC,EAAQC,KACjB,iBAATvB,IAClBC,EAAOD,EAAM,GACbA,EAAQA,EAAM,IAEhBE,EAAWF,EACXuB,EAAMA,MAAQH,EAAOG,EAAMA,OAAOtB,EAAMqB,EAAQC,GACzCrB,EACT,EACA4B,OAAQ,SAASP,EAAOsE,EAAWC,GACjC,IAAIC,EAAKxE,EAAMG,QACX3B,EAAK8F,GAAaA,EAAUjB,OAAO,GACnC9C,EAASiE,EAAGjE,OACZkE,EAAgBxB,GAAgBqB,GAChCI,EAAaH,EAAIG,WAAWH,EAAII,KAChCC,EAAoB5E,EAAMG,QAAQsB,KAAOzB,EAAMG,QAAQsB,KAAKrB,KAAKC,UAAY,GAC7EwE,EAAiB7E,EAAMG,QAAQsB,KAAOzB,EAAMG,QAAQsB,KAAKrB,KAAKG,OAASmE,EA0C3E,OAxCIF,EAAG/C,OACI,KAANjD,IAAyB,SAAXgG,EAAG9F,MAA8B,WAAX8F,EAAG9F,MAAgC,aAAX8F,EAAG9F,OACzD,KAANF,IAAyB,UAAXgG,EAAG9F,MAA+B,kBAAX8F,EAAG9F,OAClC,KAANF,GAAyB,MAAXgG,EAAG9F,MACpB6B,EAASiE,EAAGjE,OAASgE,EAAIO,KACd,OAAO1D,KAAK5C,KACnB,UAAU4C,KAAK5C,IACf,MAAM4C,KAAKkD,IACrB,gBAAgBlD,KAAKkD,IACX,WAAWlD,KAAKwD,IAChB,sCAAsCxD,KAAKkD,IACrD,yBAAyBlD,KAAKkD,IAC9B,UAAUlD,KAAKkD,IACDhC,EAAYmC,GACdlE,EAASmE,EACA,6BAA6BtD,KAAK5C,IAAO2C,EAAUsD,GAE9DlE,EADE,SAASa,KAAKwD,GACPC,EACC7E,EAAM+C,QAAU,6BAA6B3B,KAAKwD,KAAsBzD,EAAUyD,GAGnFF,EAFAA,GAAcG,EAAiBA,EAAiBA,EAAiBN,EAAIO,KAItE,QAAQ1D,KAAKkD,KAAe/B,EAAmBkC,KAAkBpC,EAAeoC,KAExFlE,EADE+B,EAAYsC,GACLF,GAAcG,EAAiBA,EAAiBA,EAAiBN,EAAIO,KACrE,MAAM1D,KAAKwD,GACXF,GAAcG,EAAiBH,EAAaG,EAAiBN,EAAIO,KACjEvC,EAAmBqC,IAAsBvC,EAAeuC,GACxDF,GAAcG,EAAiBA,EAAiBH,EAChD,mCAAmCtD,KAAKwD,IACxC,QAAQxD,KAAKwD,IACbzD,EAAUyD,IACV,qBAAqBxD,KAAKwD,GAC1BC,EAAiBN,EAAIO,KAErBJ,IAIRnE,CACT,EACAwE,aAAc,CACZC,cAAe,UACfC,cAAe,CAAC7E,KAAM,KAAMgD,MAAO,CAAC8B,KAAM,KAAMC,MAAO,OACvDC,aAAc1H,G","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/stylus.js"],"sourcesContent":["// developer.mozilla.org/en-US/docs/Web/HTML/Element\nvar tagKeywords_ = [\"a\",\"abbr\",\"address\",\"area\",\"article\",\"aside\",\"audio\", \"b\", \"base\",\"bdi\", \"bdo\",\"bgsound\",\"blockquote\",\"body\",\"br\",\"button\",\"canvas\",\"caption\",\"cite\", \"code\",\"col\",\"colgroup\",\"data\",\"datalist\",\"dd\",\"del\",\"details\",\"dfn\",\"div\", \"dl\",\"dt\",\"em\",\"embed\",\"fieldset\",\"figcaption\",\"figure\",\"footer\",\"form\",\"h1\", \"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"head\",\"header\",\"hgroup\",\"hr\",\"html\",\"i\",\"iframe\", \"img\",\"input\",\"ins\",\"kbd\",\"keygen\",\"label\",\"legend\",\"li\",\"link\",\"main\",\"map\", \"mark\",\"marquee\",\"menu\",\"menuitem\",\"meta\",\"meter\",\"nav\",\"nobr\",\"noframes\", \"noscript\",\"object\",\"ol\",\"optgroup\",\"option\",\"output\",\"p\",\"param\",\"pre\", \"progress\",\"q\",\"rp\",\"rt\",\"ruby\",\"s\",\"samp\",\"script\",\"section\",\"select\", \"small\",\"source\",\"span\",\"strong\",\"style\",\"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"textarea\",\"tfoot\",\"th\",\"thead\",\"time\",\"tr\",\"track\", \"u\",\"ul\",\"var\",\"video\"];\n\n// github.com/codemirror/CodeMirror/blob/master/mode/css/css.js\n// Note, \"url-prefix\" should precede \"url\" in order to match correctly in documentTypesRegexp\nvar documentTypes_ = [\"domain\", \"regexp\", \"url-prefix\", \"url\"];\nvar mediaTypes_ = [\"all\",\"aural\",\"braille\",\"handheld\",\"print\",\"projection\",\"screen\",\"tty\",\"tv\",\"embossed\"];\nvar mediaFeatures_ = [\"width\",\"min-width\",\"max-width\",\"height\",\"min-height\",\"max-height\",\"device-width\",\"min-device-width\",\"max-device-width\",\"device-height\",\"min-device-height\",\"max-device-height\",\"aspect-ratio\",\"min-aspect-ratio\",\"max-aspect-ratio\",\"device-aspect-ratio\",\"min-device-aspect-ratio\",\"max-device-aspect-ratio\",\"color\",\"min-color\",\"max-color\",\"color-index\",\"min-color-index\",\"max-color-index\",\"monochrome\",\"min-monochrome\",\"max-monochrome\",\"resolution\",\"min-resolution\",\"max-resolution\",\"scan\",\"grid\",\"dynamic-range\",\"video-dynamic-range\"];\nvar propertyKeywords_ = [\"align-content\",\"align-items\",\"align-self\",\"alignment-adjust\",\"alignment-baseline\",\"anchor-point\",\"animation\",\"animation-delay\",\"animation-direction\",\"animation-duration\",\"animation-fill-mode\",\"animation-iteration-count\",\"animation-name\",\"animation-play-state\",\"animation-timing-function\",\"appearance\",\"azimuth\",\"backface-visibility\",\"background\",\"background-attachment\",\"background-clip\",\"background-color\",\"background-image\",\"background-origin\",\"background-position\",\"background-repeat\",\"background-size\",\"baseline-shift\",\"binding\",\"bleed\",\"bookmark-label\",\"bookmark-level\",\"bookmark-state\",\"bookmark-target\",\"border\",\"border-bottom\",\"border-bottom-color\",\"border-bottom-left-radius\",\"border-bottom-right-radius\",\"border-bottom-style\",\"border-bottom-width\",\"border-collapse\",\"border-color\",\"border-image\",\"border-image-outset\",\"border-image-repeat\",\"border-image-slice\",\"border-image-source\",\"border-image-width\",\"border-left\",\"border-left-color\",\"border-left-style\",\"border-left-width\",\"border-radius\",\"border-right\",\"border-right-color\",\"border-right-style\",\"border-right-width\",\"border-spacing\",\"border-style\",\"border-top\",\"border-top-color\",\"border-top-left-radius\",\"border-top-right-radius\",\"border-top-style\",\"border-top-width\",\"border-width\",\"bottom\",\"box-decoration-break\",\"box-shadow\",\"box-sizing\",\"break-after\",\"break-before\",\"break-inside\",\"caption-side\",\"clear\",\"clip\",\"color\",\"color-profile\",\"column-count\",\"column-fill\",\"column-gap\",\"column-rule\",\"column-rule-color\",\"column-rule-style\",\"column-rule-width\",\"column-span\",\"column-width\",\"columns\",\"content\",\"counter-increment\",\"counter-reset\",\"crop\",\"cue\",\"cue-after\",\"cue-before\",\"cursor\",\"direction\",\"display\",\"dominant-baseline\",\"drop-initial-after-adjust\",\"drop-initial-after-align\",\"drop-initial-before-adjust\",\"drop-initial-before-align\",\"drop-initial-size\",\"drop-initial-value\",\"elevation\",\"empty-cells\",\"fit\",\"fit-position\",\"flex\",\"flex-basis\",\"flex-direction\",\"flex-flow\",\"flex-grow\",\"flex-shrink\",\"flex-wrap\",\"float\",\"float-offset\",\"flow-from\",\"flow-into\",\"font\",\"font-feature-settings\",\"font-family\",\"font-kerning\",\"font-language-override\",\"font-size\",\"font-size-adjust\",\"font-stretch\",\"font-style\",\"font-synthesis\",\"font-variant\",\"font-variant-alternates\",\"font-variant-caps\",\"font-variant-east-asian\",\"font-variant-ligatures\",\"font-variant-numeric\",\"font-variant-position\",\"font-weight\",\"grid\",\"grid-area\",\"grid-auto-columns\",\"grid-auto-flow\",\"grid-auto-position\",\"grid-auto-rows\",\"grid-column\",\"grid-column-end\",\"grid-column-start\",\"grid-row\",\"grid-row-end\",\"grid-row-start\",\"grid-template\",\"grid-template-areas\",\"grid-template-columns\",\"grid-template-rows\",\"hanging-punctuation\",\"height\",\"hyphens\",\"icon\",\"image-orientation\",\"image-rendering\",\"image-resolution\",\"inline-box-align\",\"justify-content\",\"left\",\"letter-spacing\",\"line-break\",\"line-height\",\"line-stacking\",\"line-stacking-ruby\",\"line-stacking-shift\",\"line-stacking-strategy\",\"list-style\",\"list-style-image\",\"list-style-position\",\"list-style-type\",\"margin\",\"margin-bottom\",\"margin-left\",\"margin-right\",\"margin-top\",\"marker-offset\",\"marks\",\"marquee-direction\",\"marquee-loop\",\"marquee-play-count\",\"marquee-speed\",\"marquee-style\",\"max-height\",\"max-width\",\"min-height\",\"min-width\",\"move-to\",\"nav-down\",\"nav-index\",\"nav-left\",\"nav-right\",\"nav-up\",\"object-fit\",\"object-position\",\"opacity\",\"order\",\"orphans\",\"outline\",\"outline-color\",\"outline-offset\",\"outline-style\",\"outline-width\",\"overflow\",\"overflow-style\",\"overflow-wrap\",\"overflow-x\",\"overflow-y\",\"padding\",\"padding-bottom\",\"padding-left\",\"padding-right\",\"padding-top\",\"page\",\"page-break-after\",\"page-break-before\",\"page-break-inside\",\"page-policy\",\"pause\",\"pause-after\",\"pause-before\",\"perspective\",\"perspective-origin\",\"pitch\",\"pitch-range\",\"play-during\",\"position\",\"presentation-level\",\"punctuation-trim\",\"quotes\",\"region-break-after\",\"region-break-before\",\"region-break-inside\",\"region-fragment\",\"rendering-intent\",\"resize\",\"rest\",\"rest-after\",\"rest-before\",\"richness\",\"right\",\"rotation\",\"rotation-point\",\"ruby-align\",\"ruby-overhang\",\"ruby-position\",\"ruby-span\",\"shape-image-threshold\",\"shape-inside\",\"shape-margin\",\"shape-outside\",\"size\",\"speak\",\"speak-as\",\"speak-header\",\"speak-numeral\",\"speak-punctuation\",\"speech-rate\",\"stress\",\"string-set\",\"tab-size\",\"table-layout\",\"target\",\"target-name\",\"target-new\",\"target-position\",\"text-align\",\"text-align-last\",\"text-decoration\",\"text-decoration-color\",\"text-decoration-line\",\"text-decoration-skip\",\"text-decoration-style\",\"text-emphasis\",\"text-emphasis-color\",\"text-emphasis-position\",\"text-emphasis-style\",\"text-height\",\"text-indent\",\"text-justify\",\"text-outline\",\"text-overflow\",\"text-shadow\",\"text-size-adjust\",\"text-space-collapse\",\"text-transform\",\"text-underline-position\",\"text-wrap\",\"top\",\"transform\",\"transform-origin\",\"transform-style\",\"transition\",\"transition-delay\",\"transition-duration\",\"transition-property\",\"transition-timing-function\",\"unicode-bidi\",\"vertical-align\",\"visibility\",\"voice-balance\",\"voice-duration\",\"voice-family\",\"voice-pitch\",\"voice-range\",\"voice-rate\",\"voice-stress\",\"voice-volume\",\"volume\",\"white-space\",\"widows\",\"width\",\"will-change\",\"word-break\",\"word-spacing\",\"word-wrap\",\"z-index\",\"clip-path\",\"clip-rule\",\"mask\",\"enable-background\",\"filter\",\"flood-color\",\"flood-opacity\",\"lighting-color\",\"stop-color\",\"stop-opacity\",\"pointer-events\",\"color-interpolation\",\"color-interpolation-filters\",\"color-rendering\",\"fill\",\"fill-opacity\",\"fill-rule\",\"image-rendering\",\"marker\",\"marker-end\",\"marker-mid\",\"marker-start\",\"shape-rendering\",\"stroke\",\"stroke-dasharray\",\"stroke-dashoffset\",\"stroke-linecap\",\"stroke-linejoin\",\"stroke-miterlimit\",\"stroke-opacity\",\"stroke-width\",\"text-rendering\",\"baseline-shift\",\"dominant-baseline\",\"glyph-orientation-horizontal\",\"glyph-orientation-vertical\",\"text-anchor\",\"writing-mode\",\"font-smoothing\",\"osx-font-smoothing\"];\nvar nonStandardPropertyKeywords_ = [\"scrollbar-arrow-color\",\"scrollbar-base-color\",\"scrollbar-dark-shadow-color\",\"scrollbar-face-color\",\"scrollbar-highlight-color\",\"scrollbar-shadow-color\",\"scrollbar-3d-light-color\",\"scrollbar-track-color\",\"shape-inside\",\"searchfield-cancel-button\",\"searchfield-decoration\",\"searchfield-results-button\",\"searchfield-results-decoration\",\"zoom\"];\nvar fontProperties_ = [\"font-family\",\"src\",\"unicode-range\",\"font-variant\",\"font-feature-settings\",\"font-stretch\",\"font-weight\",\"font-style\"];\nvar colorKeywords_ = [\"aliceblue\",\"antiquewhite\",\"aqua\",\"aquamarine\",\"azure\",\"beige\",\"bisque\",\"black\",\"blanchedalmond\",\"blue\",\"blueviolet\",\"brown\",\"burlywood\",\"cadetblue\",\"chartreuse\",\"chocolate\",\"coral\",\"cornflowerblue\",\"cornsilk\",\"crimson\",\"cyan\",\"darkblue\",\"darkcyan\",\"darkgoldenrod\",\"darkgray\",\"darkgreen\",\"darkkhaki\",\"darkmagenta\",\"darkolivegreen\",\"darkorange\",\"darkorchid\",\"darkred\",\"darksalmon\",\"darkseagreen\",\"darkslateblue\",\"darkslategray\",\"darkturquoise\",\"darkviolet\",\"deeppink\",\"deepskyblue\",\"dimgray\",\"dodgerblue\",\"firebrick\",\"floralwhite\",\"forestgreen\",\"fuchsia\",\"gainsboro\",\"ghostwhite\",\"gold\",\"goldenrod\",\"gray\",\"grey\",\"green\",\"greenyellow\",\"honeydew\",\"hotpink\",\"indianred\",\"indigo\",\"ivory\",\"khaki\",\"lavender\",\"lavenderblush\",\"lawngreen\",\"lemonchiffon\",\"lightblue\",\"lightcoral\",\"lightcyan\",\"lightgoldenrodyellow\",\"lightgray\",\"lightgreen\",\"lightpink\",\"lightsalmon\",\"lightseagreen\",\"lightskyblue\",\"lightslategray\",\"lightsteelblue\",\"lightyellow\",\"lime\",\"limegreen\",\"linen\",\"magenta\",\"maroon\",\"mediumaquamarine\",\"mediumblue\",\"mediumorchid\",\"mediumpurple\",\"mediumseagreen\",\"mediumslateblue\",\"mediumspringgreen\",\"mediumturquoise\",\"mediumvioletred\",\"midnightblue\",\"mintcream\",\"mistyrose\",\"moccasin\",\"navajowhite\",\"navy\",\"oldlace\",\"olive\",\"olivedrab\",\"orange\",\"orangered\",\"orchid\",\"palegoldenrod\",\"palegreen\",\"paleturquoise\",\"palevioletred\",\"papayawhip\",\"peachpuff\",\"peru\",\"pink\",\"plum\",\"powderblue\",\"purple\",\"rebeccapurple\",\"red\",\"rosybrown\",\"royalblue\",\"saddlebrown\",\"salmon\",\"sandybrown\",\"seagreen\",\"seashell\",\"sienna\",\"silver\",\"skyblue\",\"slateblue\",\"slategray\",\"snow\",\"springgreen\",\"steelblue\",\"tan\",\"teal\",\"thistle\",\"tomato\",\"turquoise\",\"violet\",\"wheat\",\"white\",\"whitesmoke\",\"yellow\",\"yellowgreen\"];\nvar valueKeywords_ = [\"above\",\"absolute\",\"activeborder\",\"additive\",\"activecaption\",\"afar\",\"after-white-space\",\"ahead\",\"alias\",\"all\",\"all-scroll\",\"alphabetic\",\"alternate\",\"always\",\"amharic\",\"amharic-abegede\",\"antialiased\",\"appworkspace\",\"arabic-indic\",\"armenian\",\"asterisks\",\"attr\",\"auto\",\"avoid\",\"avoid-column\",\"avoid-page\",\"avoid-region\",\"background\",\"backwards\",\"baseline\",\"below\",\"bidi-override\",\"binary\",\"bengali\",\"blink\",\"block\",\"block-axis\",\"bold\",\"bolder\",\"border\",\"border-box\",\"both\",\"bottom\",\"break\",\"break-all\",\"break-word\",\"bullets\",\"button\",\"buttonface\",\"buttonhighlight\",\"buttonshadow\",\"buttontext\",\"calc\",\"cambodian\",\"capitalize\",\"caps-lock-indicator\",\"caption\",\"captiontext\",\"caret\",\"cell\",\"center\",\"checkbox\",\"circle\",\"cjk-decimal\",\"cjk-earthly-branch\",\"cjk-heavenly-stem\",\"cjk-ideographic\",\"clear\",\"clip\",\"close-quote\",\"col-resize\",\"collapse\",\"column\",\"compact\",\"condensed\",\"conic-gradient\",\"contain\",\"content\",\"contents\",\"content-box\",\"context-menu\",\"continuous\",\"copy\",\"counter\",\"counters\",\"cover\",\"crop\",\"cross\",\"crosshair\",\"currentcolor\",\"cursive\",\"cyclic\",\"dashed\",\"decimal\",\"decimal-leading-zero\",\"default\",\"default-button\",\"destination-atop\",\"destination-in\",\"destination-out\",\"destination-over\",\"devanagari\",\"disc\",\"discard\",\"disclosure-closed\",\"disclosure-open\",\"document\",\"dot-dash\",\"dot-dot-dash\",\"dotted\",\"double\",\"down\",\"e-resize\",\"ease\",\"ease-in\",\"ease-in-out\",\"ease-out\",\"element\",\"ellipse\",\"ellipsis\",\"embed\",\"end\",\"ethiopic\",\"ethiopic-abegede\",\"ethiopic-abegede-am-et\",\"ethiopic-abegede-gez\",\"ethiopic-abegede-ti-er\",\"ethiopic-abegede-ti-et\",\"ethiopic-halehame-aa-er\",\"ethiopic-halehame-aa-et\",\"ethiopic-halehame-am-et\",\"ethiopic-halehame-gez\",\"ethiopic-halehame-om-et\",\"ethiopic-halehame-sid-et\",\"ethiopic-halehame-so-et\",\"ethiopic-halehame-ti-er\",\"ethiopic-halehame-ti-et\",\"ethiopic-halehame-tig\",\"ethiopic-numeric\",\"ew-resize\",\"expanded\",\"extends\",\"extra-condensed\",\"extra-expanded\",\"fantasy\",\"fast\",\"fill\",\"fixed\",\"flat\",\"flex\",\"footnotes\",\"forwards\",\"from\",\"geometricPrecision\",\"georgian\",\"graytext\",\"groove\",\"gujarati\",\"gurmukhi\",\"hand\",\"hangul\",\"hangul-consonant\",\"hebrew\",\"help\",\"hidden\",\"hide\",\"high\",\"higher\",\"highlight\",\"highlighttext\",\"hiragana\",\"hiragana-iroha\",\"horizontal\",\"hsl\",\"hsla\",\"icon\",\"ignore\",\"inactiveborder\",\"inactivecaption\",\"inactivecaptiontext\",\"infinite\",\"infobackground\",\"infotext\",\"inherit\",\"initial\",\"inline\",\"inline-axis\",\"inline-block\",\"inline-flex\",\"inline-table\",\"inset\",\"inside\",\"intrinsic\",\"invert\",\"italic\",\"japanese-formal\",\"japanese-informal\",\"justify\",\"kannada\",\"katakana\",\"katakana-iroha\",\"keep-all\",\"khmer\",\"korean-hangul-formal\",\"korean-hanja-formal\",\"korean-hanja-informal\",\"landscape\",\"lao\",\"large\",\"larger\",\"left\",\"level\",\"lighter\",\"line-through\",\"linear\",\"linear-gradient\",\"lines\",\"list-item\",\"listbox\",\"listitem\",\"local\",\"logical\",\"loud\",\"lower\",\"lower-alpha\",\"lower-armenian\",\"lower-greek\",\"lower-hexadecimal\",\"lower-latin\",\"lower-norwegian\",\"lower-roman\",\"lowercase\",\"ltr\",\"malayalam\",\"match\",\"matrix\",\"matrix3d\",\"media-play-button\",\"media-slider\",\"media-sliderthumb\",\"media-volume-slider\",\"media-volume-sliderthumb\",\"medium\",\"menu\",\"menulist\",\"menulist-button\",\"menutext\",\"message-box\",\"middle\",\"min-intrinsic\",\"mix\",\"mongolian\",\"monospace\",\"move\",\"multiple\",\"myanmar\",\"n-resize\",\"narrower\",\"ne-resize\",\"nesw-resize\",\"no-close-quote\",\"no-drop\",\"no-open-quote\",\"no-repeat\",\"none\",\"normal\",\"not-allowed\",\"nowrap\",\"ns-resize\",\"numbers\",\"numeric\",\"nw-resize\",\"nwse-resize\",\"oblique\",\"octal\",\"open-quote\",\"optimizeLegibility\",\"optimizeSpeed\",\"oriya\",\"oromo\",\"outset\",\"outside\",\"outside-shape\",\"overlay\",\"overline\",\"padding\",\"padding-box\",\"painted\",\"page\",\"paused\",\"persian\",\"perspective\",\"plus-darker\",\"plus-lighter\",\"pointer\",\"polygon\",\"portrait\",\"pre\",\"pre-line\",\"pre-wrap\",\"preserve-3d\",\"progress\",\"push-button\",\"radial-gradient\",\"radio\",\"read-only\",\"read-write\",\"read-write-plaintext-only\",\"rectangle\",\"region\",\"relative\",\"repeat\",\"repeating-linear-gradient\",\"repeating-radial-gradient\",\"repeating-conic-gradient\",\"repeat-x\",\"repeat-y\",\"reset\",\"reverse\",\"rgb\",\"rgba\",\"ridge\",\"right\",\"rotate\",\"rotate3d\",\"rotateX\",\"rotateY\",\"rotateZ\",\"round\",\"row-resize\",\"rtl\",\"run-in\",\"running\",\"s-resize\",\"sans-serif\",\"scale\",\"scale3d\",\"scaleX\",\"scaleY\",\"scaleZ\",\"scroll\",\"scrollbar\",\"scroll-position\",\"se-resize\",\"searchfield\",\"searchfield-cancel-button\",\"searchfield-decoration\",\"searchfield-results-button\",\"searchfield-results-decoration\",\"semi-condensed\",\"semi-expanded\",\"separate\",\"serif\",\"show\",\"sidama\",\"simp-chinese-formal\",\"simp-chinese-informal\",\"single\",\"skew\",\"skewX\",\"skewY\",\"skip-white-space\",\"slide\",\"slider-horizontal\",\"slider-vertical\",\"sliderthumb-horizontal\",\"sliderthumb-vertical\",\"slow\",\"small\",\"small-caps\",\"small-caption\",\"smaller\",\"solid\",\"somali\",\"source-atop\",\"source-in\",\"source-out\",\"source-over\",\"space\",\"spell-out\",\"square\",\"square-button\",\"standard\",\"start\",\"static\",\"status-bar\",\"stretch\",\"stroke\",\"sub\",\"subpixel-antialiased\",\"super\",\"sw-resize\",\"symbolic\",\"symbols\",\"table\",\"table-caption\",\"table-cell\",\"table-column\",\"table-column-group\",\"table-footer-group\",\"table-header-group\",\"table-row\",\"table-row-group\",\"tamil\",\"telugu\",\"text\",\"text-bottom\",\"text-top\",\"textarea\",\"textfield\",\"thai\",\"thick\",\"thin\",\"threeddarkshadow\",\"threedface\",\"threedhighlight\",\"threedlightshadow\",\"threedshadow\",\"tibetan\",\"tigre\",\"tigrinya-er\",\"tigrinya-er-abegede\",\"tigrinya-et\",\"tigrinya-et-abegede\",\"to\",\"top\",\"trad-chinese-formal\",\"trad-chinese-informal\",\"translate\",\"translate3d\",\"translateX\",\"translateY\",\"translateZ\",\"transparent\",\"ultra-condensed\",\"ultra-expanded\",\"underline\",\"up\",\"upper-alpha\",\"upper-armenian\",\"upper-greek\",\"upper-hexadecimal\",\"upper-latin\",\"upper-norwegian\",\"upper-roman\",\"uppercase\",\"urdu\",\"url\",\"var\",\"vertical\",\"vertical-text\",\"visible\",\"visibleFill\",\"visiblePainted\",\"visibleStroke\",\"visual\",\"w-resize\",\"wait\",\"wave\",\"wider\",\"window\",\"windowframe\",\"windowtext\",\"words\",\"x-large\",\"x-small\",\"xor\",\"xx-large\",\"xx-small\",\"bicubic\",\"optimizespeed\",\"grayscale\",\"row\",\"row-reverse\",\"wrap\",\"wrap-reverse\",\"column-reverse\",\"flex-start\",\"flex-end\",\"space-between\",\"space-around\", \"unset\"];\n\nvar wordOperatorKeywords_ = [\"in\",\"and\",\"or\",\"not\",\"is not\",\"is a\",\"is\",\"isnt\",\"defined\",\"if unless\"],\n blockKeywords_ = [\"for\",\"if\",\"else\",\"unless\", \"from\", \"to\"],\n commonAtoms_ = [\"null\",\"true\",\"false\",\"href\",\"title\",\"type\",\"not-allowed\",\"readonly\",\"disabled\"],\n commonDef_ = [\"@font-face\", \"@keyframes\", \"@media\", \"@viewport\", \"@page\", \"@host\", \"@supports\", \"@block\", \"@css\"];\n\nvar hintWords = tagKeywords_.concat(documentTypes_,mediaTypes_,mediaFeatures_,\n propertyKeywords_,nonStandardPropertyKeywords_,\n colorKeywords_,valueKeywords_,fontProperties_,\n wordOperatorKeywords_,blockKeywords_,\n commonAtoms_,commonDef_);\n\nfunction wordRegexp(words) {\n words = words.sort(function(a,b){return b > a;});\n return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\");\n}\n\nfunction keySet(array) {\n var keys = {};\n for (var i = 0; i < array.length; ++i) keys[array[i]] = true;\n return keys;\n}\n\nfunction escapeRegExp(text) {\n return text.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, \"\\\\$&\");\n}\n\nvar tagKeywords = keySet(tagKeywords_),\n tagVariablesRegexp = /^(a|b|i|s|col|em)$/i,\n propertyKeywords = keySet(propertyKeywords_),\n nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_),\n valueKeywords = keySet(valueKeywords_),\n colorKeywords = keySet(colorKeywords_),\n documentTypes = keySet(documentTypes_),\n documentTypesRegexp = wordRegexp(documentTypes_),\n mediaFeatures = keySet(mediaFeatures_),\n mediaTypes = keySet(mediaTypes_),\n fontProperties = keySet(fontProperties_),\n operatorsRegexp = /^\\s*([.]{2,3}|&&|\\|\\||\\*\\*|[?!=:]?=|[-+*\\/%<>]=?|\\?:|\\~)/,\n wordOperatorKeywordsRegexp = wordRegexp(wordOperatorKeywords_),\n blockKeywords = keySet(blockKeywords_),\n vendorPrefixesRegexp = new RegExp(/^\\-(moz|ms|o|webkit)-/i),\n commonAtoms = keySet(commonAtoms_),\n firstWordMatch = \"\",\n states = {},\n ch,\n style,\n type,\n override;\n\n/**\n * Tokenizers\n */\nfunction tokenBase(stream, state) {\n firstWordMatch = stream.string.match(/(^[\\w-]+\\s*=\\s*$)|(^\\s*[\\w-]+\\s*=\\s*[\\w-])|(^\\s*(\\.|#|@|\\$|\\&|\\[|\\d|\\+|::?|\\{|\\>|~|\\/)?\\s*[\\w-]*([a-z0-9-]|\\*|\\/\\*)(\\(|,)?)/);\n state.context.line.firstWord = firstWordMatch ? firstWordMatch[0].replace(/^\\s*/, \"\") : \"\";\n state.context.line.indent = stream.indentation();\n ch = stream.peek();\n\n // Line comment\n if (stream.match(\"//\")) {\n stream.skipToEnd();\n return [\"comment\", \"comment\"];\n }\n // Block comment\n if (stream.match(\"/*\")) {\n state.tokenize = tokenCComment;\n return tokenCComment(stream, state);\n }\n // String\n if (ch == \"\\\"\" || ch == \"'\") {\n stream.next();\n state.tokenize = tokenString(ch);\n return state.tokenize(stream, state);\n }\n // Def\n if (ch == \"@\") {\n stream.next();\n stream.eatWhile(/[\\w\\\\-]/);\n return [\"def\", stream.current()];\n }\n // ID selector or Hex color\n if (ch == \"#\") {\n stream.next();\n // Hex color\n if (stream.match(/^[0-9a-f]{3}([0-9a-f]([0-9a-f]{2}){0,2})?\\b(?!-)/i)) {\n return [\"atom\", \"atom\"];\n }\n // ID selector\n if (stream.match(/^[a-z][\\w-]*/i)) {\n return [\"builtin\", \"hash\"];\n }\n }\n // Vendor prefixes\n if (stream.match(vendorPrefixesRegexp)) {\n return [\"meta\", \"vendor-prefixes\"];\n }\n // Numbers\n if (stream.match(/^-?[0-9]?\\.?[0-9]/)) {\n stream.eatWhile(/[a-z%]/i);\n return [\"number\", \"unit\"];\n }\n // !important|optional\n if (ch == \"!\") {\n stream.next();\n return [stream.match(/^(important|optional)/i) ? \"keyword\": \"operator\", \"important\"];\n }\n // Class\n if (ch == \".\" && stream.match(/^\\.[a-z][\\w-]*/i)) {\n return [\"qualifier\", \"qualifier\"];\n }\n // url url-prefix domain regexp\n if (stream.match(documentTypesRegexp)) {\n if (stream.peek() == \"(\") state.tokenize = tokenParenthesized;\n return [\"property\", \"word\"];\n }\n // Mixins / Functions\n if (stream.match(/^[a-z][\\w-]*\\(/i)) {\n stream.backUp(1);\n return [\"keyword\", \"mixin\"];\n }\n // Block mixins\n if (stream.match(/^(\\+|-)[a-z][\\w-]*\\(/i)) {\n stream.backUp(1);\n return [\"keyword\", \"block-mixin\"];\n }\n // Parent Reference BEM naming\n if (stream.string.match(/^\\s*&/) && stream.match(/^[-_]+[a-z][\\w-]*/)) {\n return [\"qualifier\", \"qualifier\"];\n }\n // / Root Reference & Parent Reference\n if (stream.match(/^(\\/|&)(-|_|:|\\.|#|[a-z])/)) {\n stream.backUp(1);\n return [\"variableName.special\", \"reference\"];\n }\n if (stream.match(/^&{1}\\s*$/)) {\n return [\"variableName.special\", \"reference\"];\n }\n // Word operator\n if (stream.match(wordOperatorKeywordsRegexp)) {\n return [\"operator\", \"operator\"];\n }\n // Word\n if (stream.match(/^\\$?[-_]*[a-z0-9]+[\\w-]*/i)) {\n // Variable\n if (stream.match(/^(\\.|\\[)[\\w-\\'\\\"\\]]+/i, false)) {\n if (!wordIsTag(stream.current())) {\n stream.match('.');\n return [\"variable\", \"variable-name\"];\n }\n }\n return [\"variable\", \"word\"];\n }\n // Operators\n if (stream.match(operatorsRegexp)) {\n return [\"operator\", stream.current()];\n }\n // Delimiters\n if (/[:;,{}\\[\\]\\(\\)]/.test(ch)) {\n stream.next();\n return [null, ch];\n }\n // Non-detected items\n stream.next();\n return [null, null];\n}\n\n/**\n * Token comment\n */\nfunction tokenCComment(stream, state) {\n var maybeEnd = false, ch;\n while ((ch = stream.next()) != null) {\n if (maybeEnd && ch == \"/\") {\n state.tokenize = null;\n break;\n }\n maybeEnd = (ch == \"*\");\n }\n return [\"comment\", \"comment\"];\n}\n\n/**\n * Token string\n */\nfunction tokenString(quote) {\n return function(stream, state) {\n var escaped = false, ch;\n while ((ch = stream.next()) != null) {\n if (ch == quote && !escaped) {\n if (quote == \")\") stream.backUp(1);\n break;\n }\n escaped = !escaped && ch == \"\\\\\";\n }\n if (ch == quote || !escaped && quote != \")\") state.tokenize = null;\n return [\"string\", \"string\"];\n };\n}\n\n/**\n * Token parenthesized\n */\nfunction tokenParenthesized(stream, state) {\n stream.next(); // Must be \"(\"\n if (!stream.match(/\\s*[\\\"\\')]/, false))\n state.tokenize = tokenString(\")\");\n else\n state.tokenize = null;\n return [null, \"(\"];\n}\n\n/**\n * Context management\n */\nfunction Context(type, indent, prev, line) {\n this.type = type;\n this.indent = indent;\n this.prev = prev;\n this.line = line || {firstWord: \"\", indent: 0};\n}\n\nfunction pushContext(state, stream, type, indent) {\n indent = indent >= 0 ? indent : stream.indentUnit;\n state.context = new Context(type, stream.indentation() + indent, state.context);\n return type;\n}\n\nfunction popContext(state, stream, currentIndent) {\n var contextIndent = state.context.indent - stream.indentUnit;\n currentIndent = currentIndent || false;\n state.context = state.context.prev;\n if (currentIndent) state.context.indent = contextIndent;\n return state.context.type;\n}\n\nfunction pass(type, stream, state) {\n return states[state.context.type](type, stream, state);\n}\n\nfunction popAndPass(type, stream, state, n) {\n for (var i = n || 1; i > 0; i--)\n state.context = state.context.prev;\n return pass(type, stream, state);\n}\n\n\n/**\n * Parser\n */\nfunction wordIsTag(word) {\n return word.toLowerCase() in tagKeywords;\n}\n\nfunction wordIsProperty(word) {\n word = word.toLowerCase();\n return word in propertyKeywords || word in fontProperties;\n}\n\nfunction wordIsBlock(word) {\n return word.toLowerCase() in blockKeywords;\n}\n\nfunction wordIsVendorPrefix(word) {\n return word.toLowerCase().match(vendorPrefixesRegexp);\n}\n\nfunction wordAsValue(word) {\n var wordLC = word.toLowerCase();\n var override = \"variable\";\n if (wordIsTag(word)) override = \"tag\";\n else if (wordIsBlock(word)) override = \"block-keyword\";\n else if (wordIsProperty(word)) override = \"property\";\n else if (wordLC in valueKeywords || wordLC in commonAtoms) override = \"atom\";\n else if (wordLC == \"return\" || wordLC in colorKeywords) override = \"keyword\";\n\n // Font family\n else if (word.match(/^[A-Z]/)) override = \"string\";\n return override;\n}\n\nfunction typeIsBlock(type, stream) {\n return ((endOfLine(stream) && (type == \"{\" || type == \"]\" || type == \"hash\" || type == \"qualifier\")) || type == \"block-mixin\");\n}\n\nfunction typeIsInterpolation(type, stream) {\n return type == \"{\" && stream.match(/^\\s*\\$?[\\w-]+/i, false);\n}\n\nfunction typeIsPseudo(type, stream) {\n return type == \":\" && stream.match(/^[a-z-]+/, false);\n}\n\nfunction startOfLine(stream) {\n return stream.sol() || stream.string.match(new RegExp(\"^\\\\s*\" + escapeRegExp(stream.current())));\n}\n\nfunction endOfLine(stream) {\n return stream.eol() || stream.match(/^\\s*$/, false);\n}\n\nfunction firstWordOfLine(line) {\n var re = /^\\s*[-_]*[a-z0-9]+[\\w-]*/i;\n var result = typeof line == \"string\" ? line.match(re) : line.string.match(re);\n return result ? result[0].replace(/^\\s*/, \"\") : \"\";\n}\n\n\n/**\n * Block\n */\nstates.block = function(type, stream, state) {\n if ((type == \"comment\" && startOfLine(stream)) ||\n (type == \",\" && endOfLine(stream)) ||\n type == \"mixin\") {\n return pushContext(state, stream, \"block\", 0);\n }\n if (typeIsInterpolation(type, stream)) {\n return pushContext(state, stream, \"interpolation\");\n }\n if (endOfLine(stream) && type == \"]\") {\n if (!/^\\s*(\\.|#|:|\\[|\\*|&)/.test(stream.string) && !wordIsTag(firstWordOfLine(stream))) {\n return pushContext(state, stream, \"block\", 0);\n }\n }\n if (typeIsBlock(type, stream)) {\n return pushContext(state, stream, \"block\");\n }\n if (type == \"}\" && endOfLine(stream)) {\n return pushContext(state, stream, \"block\", 0);\n }\n if (type == \"variable-name\") {\n if (stream.string.match(/^\\s?\\$[\\w-\\.\\[\\]\\'\\\"]+$/) || wordIsBlock(firstWordOfLine(stream))) {\n return pushContext(state, stream, \"variableName\");\n }\n else {\n return pushContext(state, stream, \"variableName\", 0);\n }\n }\n if (type == \"=\") {\n if (!endOfLine(stream) && !wordIsBlock(firstWordOfLine(stream))) {\n return pushContext(state, stream, \"block\", 0);\n }\n return pushContext(state, stream, \"block\");\n }\n if (type == \"*\") {\n if (endOfLine(stream) || stream.match(/\\s*(,|\\.|#|\\[|:|{)/,false)) {\n override = \"tag\";\n return pushContext(state, stream, \"block\");\n }\n }\n if (typeIsPseudo(type, stream)) {\n return pushContext(state, stream, \"pseudo\");\n }\n if (/@(font-face|media|supports|(-moz-)?document)/.test(type)) {\n return pushContext(state, stream, endOfLine(stream) ? \"block\" : \"atBlock\");\n }\n if (/@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {\n return pushContext(state, stream, \"keyframes\");\n }\n if (/@extends?/.test(type)) {\n return pushContext(state, stream, \"extend\", 0);\n }\n if (type && type.charAt(0) == \"@\") {\n\n // Property Lookup\n if (stream.indentation() > 0 && wordIsProperty(stream.current().slice(1))) {\n override = \"variable\";\n return \"block\";\n }\n if (/(@import|@require|@charset)/.test(type)) {\n return pushContext(state, stream, \"block\", 0);\n }\n return pushContext(state, stream, \"block\");\n }\n if (type == \"reference\" && endOfLine(stream)) {\n return pushContext(state, stream, \"block\");\n }\n if (type == \"(\") {\n return pushContext(state, stream, \"parens\");\n }\n\n if (type == \"vendor-prefixes\") {\n return pushContext(state, stream, \"vendorPrefixes\");\n }\n if (type == \"word\") {\n var word = stream.current();\n override = wordAsValue(word);\n\n if (override == \"property\") {\n if (startOfLine(stream)) {\n return pushContext(state, stream, \"block\", 0);\n } else {\n override = \"atom\";\n return \"block\";\n }\n }\n\n if (override == \"tag\") {\n\n // tag is a css value\n if (/embed|menu|pre|progress|sub|table/.test(word)) {\n if (wordIsProperty(firstWordOfLine(stream))) {\n override = \"atom\";\n return \"block\";\n }\n }\n\n // tag is an attribute\n if (stream.string.match(new RegExp(\"\\\\[\\\\s*\" + word + \"|\" + word +\"\\\\s*\\\\]\"))) {\n override = \"atom\";\n return \"block\";\n }\n\n // tag is a variable\n if (tagVariablesRegexp.test(word)) {\n if ((startOfLine(stream) && stream.string.match(/=/)) ||\n (!startOfLine(stream) &&\n !stream.string.match(/^(\\s*\\.|#|\\&|\\[|\\/|>|\\*)/) &&\n !wordIsTag(firstWordOfLine(stream)))) {\n override = \"variable\";\n if (wordIsBlock(firstWordOfLine(stream))) return \"block\";\n return pushContext(state, stream, \"block\", 0);\n }\n }\n\n if (endOfLine(stream)) return pushContext(state, stream, \"block\");\n }\n if (override == \"block-keyword\") {\n override = \"keyword\";\n\n // Postfix conditionals\n if (stream.current(/(if|unless)/) && !startOfLine(stream)) {\n return \"block\";\n }\n return pushContext(state, stream, \"block\");\n }\n if (word == \"return\") return pushContext(state, stream, \"block\", 0);\n\n // Placeholder selector\n if (override == \"variable\" && stream.string.match(/^\\s?\\$[\\w-\\.\\[\\]\\'\\\"]+$/)) {\n return pushContext(state, stream, \"block\");\n }\n }\n return state.context.type;\n};\n\n\n/**\n * Parens\n */\nstates.parens = function(type, stream, state) {\n if (type == \"(\") return pushContext(state, stream, \"parens\");\n if (type == \")\") {\n if (state.context.prev.type == \"parens\") {\n return popContext(state, stream);\n }\n if ((stream.string.match(/^[a-z][\\w-]*\\(/i) && endOfLine(stream)) ||\n wordIsBlock(firstWordOfLine(stream)) ||\n /(\\.|#|:|\\[|\\*|&|>|~|\\+|\\/)/.test(firstWordOfLine(stream)) ||\n (!stream.string.match(/^-?[a-z][\\w-\\.\\[\\]\\'\\\"]*\\s*=/) &&\n wordIsTag(firstWordOfLine(stream)))) {\n return pushContext(state, stream, \"block\");\n }\n if (stream.string.match(/^[\\$-]?[a-z][\\w-\\.\\[\\]\\'\\\"]*\\s*=/) ||\n stream.string.match(/^\\s*(\\(|\\)|[0-9])/) ||\n stream.string.match(/^\\s+[a-z][\\w-]*\\(/i) ||\n stream.string.match(/^\\s+[\\$-]?[a-z]/i)) {\n return pushContext(state, stream, \"block\", 0);\n }\n if (endOfLine(stream)) return pushContext(state, stream, \"block\");\n else return pushContext(state, stream, \"block\", 0);\n }\n if (type && type.charAt(0) == \"@\" && wordIsProperty(stream.current().slice(1))) {\n override = \"variable\";\n }\n if (type == \"word\") {\n var word = stream.current();\n override = wordAsValue(word);\n if (override == \"tag\" && tagVariablesRegexp.test(word)) {\n override = \"variable\";\n }\n if (override == \"property\" || word == \"to\") override = \"atom\";\n }\n if (type == \"variable-name\") {\n return pushContext(state, stream, \"variableName\");\n }\n if (typeIsPseudo(type, stream)) {\n return pushContext(state, stream, \"pseudo\");\n }\n return state.context.type;\n};\n\n\n/**\n * Vendor prefixes\n */\nstates.vendorPrefixes = function(type, stream, state) {\n if (type == \"word\") {\n override = \"property\";\n return pushContext(state, stream, \"block\", 0);\n }\n return popContext(state, stream);\n};\n\n\n/**\n * Pseudo\n */\nstates.pseudo = function(type, stream, state) {\n if (!wordIsProperty(firstWordOfLine(stream.string))) {\n stream.match(/^[a-z-]+/);\n override = \"variableName.special\";\n if (endOfLine(stream)) return pushContext(state, stream, \"block\");\n return popContext(state, stream);\n }\n return popAndPass(type, stream, state);\n};\n\n\n/**\n * atBlock\n */\nstates.atBlock = function(type, stream, state) {\n if (type == \"(\") return pushContext(state, stream, \"atBlock_parens\");\n if (typeIsBlock(type, stream)) {\n return pushContext(state, stream, \"block\");\n }\n if (typeIsInterpolation(type, stream)) {\n return pushContext(state, stream, \"interpolation\");\n }\n if (type == \"word\") {\n var word = stream.current().toLowerCase();\n if (/^(only|not|and|or)$/.test(word))\n override = \"keyword\";\n else if (documentTypes.hasOwnProperty(word))\n override = \"tag\";\n else if (mediaTypes.hasOwnProperty(word))\n override = \"attribute\";\n else if (mediaFeatures.hasOwnProperty(word))\n override = \"property\";\n else if (nonStandardPropertyKeywords.hasOwnProperty(word))\n override = \"string.special\";\n else override = wordAsValue(stream.current());\n if (override == \"tag\" && endOfLine(stream)) {\n return pushContext(state, stream, \"block\");\n }\n }\n if (type == \"operator\" && /^(not|and|or)$/.test(stream.current())) {\n override = \"keyword\";\n }\n return state.context.type;\n};\n\nstates.atBlock_parens = function(type, stream, state) {\n if (type == \"{\" || type == \"}\") return state.context.type;\n if (type == \")\") {\n if (endOfLine(stream)) return pushContext(state, stream, \"block\");\n else return pushContext(state, stream, \"atBlock\");\n }\n if (type == \"word\") {\n var word = stream.current().toLowerCase();\n override = wordAsValue(word);\n if (/^(max|min)/.test(word)) override = \"property\";\n if (override == \"tag\") {\n tagVariablesRegexp.test(word) ? override = \"variable\" : override = \"atom\";\n }\n return state.context.type;\n }\n return states.atBlock(type, stream, state);\n};\n\n\n/**\n * Keyframes\n */\nstates.keyframes = function(type, stream, state) {\n if (stream.indentation() == \"0\" && ((type == \"}\" && startOfLine(stream)) || type == \"]\" || type == \"hash\"\n || type == \"qualifier\" || wordIsTag(stream.current()))) {\n return popAndPass(type, stream, state);\n }\n if (type == \"{\") return pushContext(state, stream, \"keyframes\");\n if (type == \"}\") {\n if (startOfLine(stream)) return popContext(state, stream, true);\n else return pushContext(state, stream, \"keyframes\");\n }\n if (type == \"unit\" && /^[0-9]+\\%$/.test(stream.current())) {\n return pushContext(state, stream, \"keyframes\");\n }\n if (type == \"word\") {\n override = wordAsValue(stream.current());\n if (override == \"block-keyword\") {\n override = \"keyword\";\n return pushContext(state, stream, \"keyframes\");\n }\n }\n if (/@(font-face|media|supports|(-moz-)?document)/.test(type)) {\n return pushContext(state, stream, endOfLine(stream) ? \"block\" : \"atBlock\");\n }\n if (type == \"mixin\") {\n return pushContext(state, stream, \"block\", 0);\n }\n return state.context.type;\n};\n\n\n/**\n * Interpolation\n */\nstates.interpolation = function(type, stream, state) {\n if (type == \"{\") popContext(state, stream) && pushContext(state, stream, \"block\");\n if (type == \"}\") {\n if (stream.string.match(/^\\s*(\\.|#|:|\\[|\\*|&|>|~|\\+|\\/)/i) ||\n (stream.string.match(/^\\s*[a-z]/i) && wordIsTag(firstWordOfLine(stream)))) {\n return pushContext(state, stream, \"block\");\n }\n if (!stream.string.match(/^(\\{|\\s*\\&)/) ||\n stream.match(/\\s*[\\w-]/,false)) {\n return pushContext(state, stream, \"block\", 0);\n }\n return pushContext(state, stream, \"block\");\n }\n if (type == \"variable-name\") {\n return pushContext(state, stream, \"variableName\", 0);\n }\n if (type == \"word\") {\n override = wordAsValue(stream.current());\n if (override == \"tag\") override = \"atom\";\n }\n return state.context.type;\n};\n\n\n/**\n * Extend/s\n */\nstates.extend = function(type, stream, state) {\n if (type == \"[\" || type == \"=\") return \"extend\";\n if (type == \"]\") return popContext(state, stream);\n if (type == \"word\") {\n override = wordAsValue(stream.current());\n return \"extend\";\n }\n return popContext(state, stream);\n};\n\n\n/**\n * Variable name\n */\nstates.variableName = function(type, stream, state) {\n if (type == \"string\" || type == \"[\" || type == \"]\" || stream.current().match(/^(\\.|\\$)/)) {\n if (stream.current().match(/^\\.[\\w-]+/i)) override = \"variable\";\n return \"variableName\";\n }\n return popAndPass(type, stream, state);\n};\n\nexport const stylus = {\n name: \"stylus\",\n startState: function() {\n return {\n tokenize: null,\n state: \"block\",\n context: new Context(\"block\", 0, null)\n };\n },\n token: function(stream, state) {\n if (!state.tokenize && stream.eatSpace()) return null;\n style = (state.tokenize || tokenBase)(stream, state);\n if (style && typeof style == \"object\") {\n type = style[1];\n style = style[0];\n }\n override = style;\n state.state = states[state.state](type, stream, state);\n return override;\n },\n indent: function(state, textAfter, iCx) {\n var cx = state.context,\n ch = textAfter && textAfter.charAt(0),\n indent = cx.indent,\n lineFirstWord = firstWordOfLine(textAfter),\n lineIndent = iCx.lineIndent(iCx.pos),\n prevLineFirstWord = state.context.prev ? state.context.prev.line.firstWord : \"\",\n prevLineIndent = state.context.prev ? state.context.prev.line.indent : lineIndent;\n\n if (cx.prev &&\n (ch == \"}\" && (cx.type == \"block\" || cx.type == \"atBlock\" || cx.type == \"keyframes\") ||\n ch == \")\" && (cx.type == \"parens\" || cx.type == \"atBlock_parens\") ||\n ch == \"{\" && (cx.type == \"at\"))) {\n indent = cx.indent - iCx.unit;\n } else if (!(/(\\})/.test(ch))) {\n if (/@|\\$|\\d/.test(ch) ||\n /^\\{/.test(textAfter) ||\n/^\\s*\\/(\\/|\\*)/.test(textAfter) ||\n /^\\s*\\/\\*/.test(prevLineFirstWord) ||\n /^\\s*[\\w-\\.\\[\\]\\'\\\"]+\\s*(\\?|:|\\+)?=/i.test(textAfter) ||\n/^(\\+|-)?[a-z][\\w-]*\\(/i.test(textAfter) ||\n/^return/.test(textAfter) ||\n wordIsBlock(lineFirstWord)) {\n indent = lineIndent;\n } else if (/(\\.|#|:|\\[|\\*|&|>|~|\\+|\\/)/.test(ch) || wordIsTag(lineFirstWord)) {\n if (/\\,\\s*$/.test(prevLineFirstWord)) {\n indent = prevLineIndent;\n } else if (!state.sol() && (/(\\.|#|:|\\[|\\*|&|>|~|\\+|\\/)/.test(prevLineFirstWord) || wordIsTag(prevLineFirstWord))) {\n indent = lineIndent <= prevLineIndent ? prevLineIndent : prevLineIndent + iCx.unit;\n } else {\n indent = lineIndent;\n }\n } else if (!/,\\s*$/.test(textAfter) && (wordIsVendorPrefix(lineFirstWord) || wordIsProperty(lineFirstWord))) {\n if (wordIsBlock(prevLineFirstWord)) {\n indent = lineIndent <= prevLineIndent ? prevLineIndent : prevLineIndent + iCx.unit;\n } else if (/^\\{/.test(prevLineFirstWord)) {\n indent = lineIndent <= prevLineIndent ? lineIndent : prevLineIndent + iCx.unit;\n } else if (wordIsVendorPrefix(prevLineFirstWord) || wordIsProperty(prevLineFirstWord)) {\n indent = lineIndent >= prevLineIndent ? prevLineIndent : lineIndent;\n } else if (/^(\\.|#|:|\\[|\\*|&|@|\\+|\\-|>|~|\\/)/.test(prevLineFirstWord) ||\n /=\\s*$/.test(prevLineFirstWord) ||\n wordIsTag(prevLineFirstWord) ||\n /^\\$[\\w-\\.\\[\\]\\'\\\"]/.test(prevLineFirstWord)) {\n indent = prevLineIndent + iCx.unit;\n } else {\n indent = lineIndent;\n }\n }\n }\n return indent;\n },\n languageData: {\n indentOnInput: /^\\s*\\}$/,\n commentTokens: {line: \"//\", block: {open: \"/*\", close: \"*/\"}},\n autocomplete: hintWords\n }\n};\n"],"names":["tagKeywords_","documentTypes_","mediaTypes_","mediaFeatures_","propertyKeywords_","nonStandardPropertyKeywords_","fontProperties_","colorKeywords_","valueKeywords_","wordOperatorKeywords_","blockKeywords_","commonAtoms_","hintWords","concat","wordRegexp","words","sort","a","b","RegExp","join","keySet","array","keys","i","length","ch","style","type","override","tagKeywords","tagVariablesRegexp","propertyKeywords","nonStandardPropertyKeywords","valueKeywords","colorKeywords","documentTypes","documentTypesRegexp","mediaFeatures","mediaTypes","fontProperties","operatorsRegexp","wordOperatorKeywordsRegexp","blockKeywords","vendorPrefixesRegexp","commonAtoms","firstWordMatch","states","tokenBase","stream","state","string","match","context","line","firstWord","replace","indent","indentation","peek","skipToEnd","tokenize","tokenCComment","next","tokenString","eatWhile","current","tokenParenthesized","backUp","wordIsTag","test","maybeEnd","quote","escaped","Context","prev","this","pushContext","indentUnit","popContext","currentIndent","contextIndent","popAndPass","n","pass","word","toLowerCase","wordIsProperty","wordIsBlock","wordIsVendorPrefix","wordAsValue","wordLC","typeIsBlock","endOfLine","typeIsInterpolation","typeIsPseudo","startOfLine","sol","eol","firstWordOfLine","re","result","block","charAt","slice","parens","vendorPrefixes","pseudo","atBlock","hasOwnProperty","atBlock_parens","keyframes","interpolation","extend","variableName","stylus","name","startState","token","eatSpace","textAfter","iCx","cx","lineFirstWord","lineIndent","pos","prevLineFirstWord","prevLineIndent","unit","languageData","indentOnInput","commentTokens","open","close","autocomplete"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/1757.index.js b/book/_build/html/_static/1757.index.js
new file mode 100644
index 0000000..c4e406f
--- /dev/null
+++ b/book/_build/html/_static/1757.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[1757],{51757:(e,t,n)=>{n.r(t),n.d(t,{vb:()=>F});var r="error";function a(e){return new RegExp("^(("+e.join(")|(")+"))\\b","i")}var i=new RegExp("^[\\+\\-\\*/%&\\\\|\\^~<>!]"),o=new RegExp("^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]"),c=new RegExp("^((==)|(<>)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))"),s=new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))"),u=new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))"),l=new RegExp("^[_A-Za-z][_A-Za-z0-9]*"),d=["class","module","sub","enum","select","while","if","function","get","set","property","try","structure","synclock","using","with"],h=["else","elseif","case","catch","finally"],m=["next","loop"],f=["and","andalso","or","orelse","xor","in","not","is","isnot","like"],p=a(f),b=["#const","#else","#elseif","#end","#if","#region","addhandler","addressof","alias","as","byref","byval","cbool","cbyte","cchar","cdate","cdbl","cdec","cint","clng","cobj","compare","const","continue","csbyte","cshort","csng","cstr","cuint","culng","cushort","declare","default","delegate","dim","directcast","each","erase","error","event","exit","explicit","false","for","friend","gettype","goto","handles","implements","imports","infer","inherits","interface","isfalse","istrue","lib","me","mod","mustinherit","mustoverride","my","mybase","myclass","namespace","narrowing","new","nothing","notinheritable","notoverridable","of","off","on","operator","option","optional","out","overloads","overridable","overrides","paramarray","partial","private","protected","public","raiseevent","readonly","redim","removehandler","resume","return","shadows","shared","static","step","stop","strict","then","throw","to","true","trycast","typeof","until","until","when","widening","withevents","writeonly"],g=["object","boolean","char","string","byte","sbyte","short","ushort","int16","uint16","integer","uinteger","int32","uint32","long","ulong","int64","uint64","decimal","single","double","float","date","datetime","intptr","uintptr"],k=a(b),y=a(g),v='"',w=a(d),x=a(h),I=a(m),z=a(["end"]),L=a(["do"]);function E(e,t){t.currentIndent++}function C(e,t){t.currentIndent--}function R(e,t){if(e.eatSpace())return null;var n,a,d;if("'"===e.peek())return e.skipToEnd(),"comment";if(e.match(/^((&H)|(&O))?[0-9\.a-f]/i,!1)){var h=!1;if((e.match(/^\d*\.\d+F?/i)||e.match(/^\d+\.\d*F?/)||e.match(/^\.\d+F?/))&&(h=!0),h)return e.eat(/J/i),"number";var m=!1;if(e.match(/^&H[0-9a-f]+/i)||e.match(/^&O[0-7]+/i)?m=!0:e.match(/^[1-9]\d*F?/)?(e.eat(/J/i),m=!0):e.match(/^0(?![\dx])/i)&&(m=!0),m)return e.eat(/L/i),"number"}return e.match(v)?(t.tokenize=(n=e.current(),a=1==n.length,d="string",function(e,t){for(;!e.eol();){if(e.eatWhile(/[^'"]/),e.match(n))return t.tokenize=R,d;e.eat(/['"]/)}return a&&(t.tokenize=R),d}),t.tokenize(e,t)):e.match(u)||e.match(s)?null:e.match(c)||e.match(i)||e.match(p)?"operator":e.match(o)?null:e.match(L)?(E(0,t),t.doInCurrentLine=!0,"keyword"):e.match(w)?(t.doInCurrentLine?t.doInCurrentLine=!1:E(0,t),"keyword"):e.match(x)?"keyword":e.match(z)?(C(0,t),C(0,t),"keyword"):e.match(I)?(C(0,t),"keyword"):e.match(y)||e.match(k)?"keyword":e.match(l)?"variable":(e.next(),r)}const F={name:"vb",startState:function(){return{tokenize:R,lastToken:null,currentIndent:0,nextLineIndent:0,doInCurrentLine:!1}},token:function(e,t){e.sol()&&(t.currentIndent+=t.nextLineIndent,t.nextLineIndent=0,t.doInCurrentLine=0);var n=function(e,t){var n=t.tokenize(e,t),a=e.current();if("."===a)return"variable"===(n=t.tokenize(e,t))?"variable":r;var i="[({".indexOf(a);return-1!==i&&E(0,t),-1!==(i="])}".indexOf(a))&&C(0,t)?r:n}(e,t);return t.lastToken={style:n,content:e.current()},n},indent:function(e,t,n){var r=t.replace(/^\s+|\s+$/g,"");return r.match(I)||r.match(z)||r.match(x)?n.unit*(e.currentIndent-1):e.currentIndent<0?0:e.currentIndent*n.unit},languageData:{closeBrackets:{brackets:["(","[","{",'"']},commentTokens:{line:"'"},autocomplete:d.concat(h).concat(m).concat(f).concat(b).concat(g)}}}}]);
+//# sourceMappingURL=1757.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/1757.index.js.map b/book/_build/html/_static/1757.index.js.map
new file mode 100644
index 0000000..874e36e
--- /dev/null
+++ b/book/_build/html/_static/1757.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"1757.index.js","mappings":"wHAAA,IAAIA,EAAa,QAEjB,SAASC,EAAWC,GAClB,OAAO,IAAIC,OAAO,MAAQD,EAAME,KAAK,OAAS,QAAS,IACzD,CAEA,IAAIC,EAAkB,IAAIF,OAAO,+BAC7BG,EAAmB,IAAIH,OAAO,kCAC9BI,EAAkB,IAAIJ,OAAO,uDAC7BK,EAAmB,IAAIL,OAAO,wDAC9BM,EAAmB,IAAIN,OAAO,kCAC9BO,EAAc,IAAIP,OAAO,2BAEzBQ,EAAkB,CAAC,QAAQ,SAAU,MAAM,OAAO,SAAS,QAAQ,KAAK,WAAY,MAAM,MAAM,WAAY,MAAO,YAAa,WAAY,QAAS,QACrJC,EAAiB,CAAC,OAAO,SAAS,OAAQ,QAAS,WACnDC,EAAc,CAAC,OAAO,QAEtBC,EAAmB,CAAC,MAAO,UAAW,KAAM,SAAU,MAAO,KAAM,MAAO,KAAM,QAAS,QACzFC,EAAgBd,EAAWa,GAE3BE,EAAiB,CAAC,SAAU,QAAS,UAAW,OAAQ,MAAO,UAAW,aAAc,YAAa,QAAS,KAAM,QAAS,QAAS,QAAS,QAAS,QAAS,QAAS,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,UAAW,QAAS,WAAY,SAAU,SAAU,OAAQ,OAAQ,QAAS,QAAS,UAAW,UAAW,UAAW,WAAY,MAAO,aAAc,OAAQ,QAAS,QAAS,QAAS,OAAQ,WAAY,QAAS,MAAO,SAAU,UAAW,OAAQ,UAAW,aAAc,UAAW,QAAS,WAAY,YAAa,UAAW,SAAU,MAAO,KAAM,MAAO,cAAe,eAAgB,KAAM,SAAU,UAAW,YAAa,YAAa,MAAO,UAAW,iBAAkB,iBAAkB,KAAM,MAAO,KAAM,WAAY,SAAU,WAAY,MAAO,YAAa,cAAe,YAAa,aAAc,UAAW,UAAW,YAAa,SAAU,aAAc,WAAY,QAAS,gBAAiB,SAAU,SAAU,UAAW,SAAU,SAAU,OAAQ,OAAQ,SAAU,OAAQ,QAAS,KAAM,OAAQ,UAAW,SAAU,QAAS,QAAS,OAAQ,WAAY,aAAc,aAEhlCC,EAAc,CAAC,SAAU,UAAW,OAAQ,SAAU,OAAQ,QAAS,QAAS,SAAU,QAAS,SAAU,UAAW,WAAY,QAAS,SAAU,OAAQ,QAAS,QAAS,SAAU,UAAW,SAAU,SAAU,QAAS,OAAQ,WAAY,SAAU,WAEjQC,EAAWjB,EAAWe,GACtBG,EAAQlB,EAAWgB,GACnBG,EAAiB,IAEjBC,EAAUpB,EAAWU,GACrBW,EAASrB,EAAWW,GACpBW,EAAUtB,EAAWY,GACrBW,EAAgBvB,EAAW,CAAC,QAC5BwB,EAAYxB,EAAW,CAAC,OAI5B,SAASyB,EAAOC,EAASC,GACvBA,EAAMC,eACR,CAEA,SAASC,EAAOH,EAASC,GACvBA,EAAMC,eACR,CAEA,SAASE,EAAUC,EAAQJ,GACzB,GAAII,EAAOC,WACT,OAAO,KAGT,IAyG0BC,EACtBC,EACAC,EAxGJ,GAAW,MAHFJ,EAAOK,OAKd,OADAL,EAAOM,YACA,UAKT,GAAIN,EAAOO,MAAM,4BAA4B,GAAQ,CACnD,IAAIC,GAAe,EAMnB,IAJIR,EAAOO,MAAM,iBACRP,EAAOO,MAAM,gBACbP,EAAOO,MAAM,eAFcC,GAAe,GAI/CA,EAGF,OADAR,EAAOS,IAAI,MACJ,SAGT,IAAIC,GAAa,EAcjB,GAZIV,EAAOO,MAAM,kBAERP,EAAOO,MAAM,cAFeG,GAAa,EAIzCV,EAAOO,MAAM,gBAEpBP,EAAOS,IAAI,MAEXC,GAAa,GAGNV,EAAOO,MAAM,kBAAmBG,GAAa,GAClDA,EAGF,OADAV,EAAOS,IAAI,MACJ,QAEX,CAGA,OAAIT,EAAOO,MAAMnB,IACfQ,EAAMe,UA2DkBT,EA3DYF,EAAOY,UA4DzCT,EAAiC,GAApBD,EAAUW,OACvBT,EAAW,SAER,SAASJ,EAAQJ,GACtB,MAAQI,EAAOc,OAAO,CAEpB,GADAd,EAAOe,SAAS,SACZf,EAAOO,MAAML,GAEf,OADAN,EAAMe,SAAWZ,EACVK,EAEPJ,EAAOS,IAAI,OAEf,CAIA,OAHIN,IACFP,EAAMe,SAAWZ,GAEZK,CACT,GA5ESR,EAAMe,SAASX,EAAQJ,IAI5BI,EAAOO,MAAM9B,IAAqBuB,EAAOO,MAAM/B,GAC1C,KAELwB,EAAOO,MAAMhC,IACVyB,EAAOO,MAAMlC,IACb2B,EAAOO,MAAMxB,GACX,WAELiB,EAAOO,MAAMjC,GACR,KAEL0B,EAAOO,MAAMd,IACfC,EAAOM,EAAOJ,GACdA,EAAMoB,iBAAkB,EACjB,WAELhB,EAAOO,MAAMlB,IACTO,EAAMoB,gBAGVpB,EAAMoB,iBAAkB,EAFxBtB,EAAOM,EAAOJ,GAGT,WAELI,EAAOO,MAAMjB,GACR,UAGLU,EAAOO,MAAMf,IACfM,EAAOE,EAAOJ,GACdE,EAAOE,EAAOJ,GACP,WAELI,EAAOO,MAAMhB,IACfO,EAAOE,EAAOJ,GACP,WAGLI,EAAOO,MAAMpB,IAIba,EAAOO,MAAMrB,GAHR,UAOLc,EAAOO,MAAM7B,GACR,YAITsB,EAAOiB,OACAjD,EACT,CA0DO,MAAMkD,EAAK,CAChBC,KAAM,KAENC,WAAY,WACV,MAAO,CACLT,SAAUZ,EACVsB,UAAW,KACXxB,cAAe,EACfyB,eAAgB,EAChBN,iBAAiB,EAIrB,EAEAO,MAAO,SAASvB,EAAQJ,GAClBI,EAAOwB,QACT5B,EAAMC,eAAiBD,EAAM0B,eAC7B1B,EAAM0B,eAAiB,EACvB1B,EAAMoB,gBAAkB,GAE1B,IAAIS,EAvDR,SAAoBzB,EAAQJ,GAC1B,IAAI6B,EAAQ7B,EAAMe,SAASX,EAAQJ,GAC/BgB,EAAUZ,EAAOY,UAGrB,GAAgB,MAAZA,EAEF,MAAc,cADda,EAAQ7B,EAAMe,SAASX,EAAQJ,IAEtB,WAEA5B,EAKX,IAAI0D,EAAkB,MAAMC,QAAQf,GAIpC,OAHyB,IAArBc,GACFhC,EAAOM,EAAQJ,IAQQ,KADzB8B,EAAkB,MAAMC,QAAQf,KAE1Bd,EAAOE,EAAQJ,GALV5B,EAUJyD,CACT,CAuBgBG,CAAW5B,EAAQJ,GAM/B,OAJAA,EAAMyB,UAAY,CAACI,MAAMA,EAAOI,QAAS7B,EAAOY,WAIzCa,CACT,EAEA/B,OAAQ,SAASE,EAAOkC,EAAWC,GACjC,IAAIC,EAAWF,EAAUG,QAAQ,aAAc,IAC/C,OAAID,EAASzB,MAAMhB,IAAYyC,EAASzB,MAAMf,IAAkBwC,EAASzB,MAAMjB,GAAgByC,EAAGG,MAAMtC,EAAMC,cAAc,GACzHD,EAAMC,cAAgB,EAAU,EAC5BD,EAAMC,cAAgBkC,EAAGG,IAClC,EAEAC,aAAc,CACZC,cAAe,CAACC,SAAU,CAAC,IAAK,IAAK,IAAK,MAC1CC,cAAe,CAACC,KAAM,KACtBC,aAAc7D,EAAgB8D,OAAO7D,GAAgB6D,OAAO5D,GACzD4D,OAAO3D,GAAkB2D,OAAOzD,GAAgByD,OAAOxD,I","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/vb.js"],"sourcesContent":["var ERRORCLASS = 'error';\n\nfunction wordRegexp(words) {\n return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\", \"i\");\n}\n\nvar singleOperators = new RegExp(\"^[\\\\+\\\\-\\\\*/%&\\\\\\\\|\\\\^~<>!]\");\nvar singleDelimiters = new RegExp('^[\\\\(\\\\)\\\\[\\\\]\\\\{\\\\}@,:`=;\\\\.]');\nvar doubleOperators = new RegExp(\"^((==)|(<>)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\\\*\\\\*))\");\nvar doubleDelimiters = new RegExp(\"^((\\\\+=)|(\\\\-=)|(\\\\*=)|(%=)|(/=)|(&=)|(\\\\|=)|(\\\\^=))\");\nvar tripleDelimiters = new RegExp(\"^((//=)|(>>=)|(<<=)|(\\\\*\\\\*=))\");\nvar identifiers = new RegExp(\"^[_A-Za-z][_A-Za-z0-9]*\");\n\nvar openingKeywords = ['class','module', 'sub','enum','select','while','if','function', 'get','set','property', 'try', 'structure', 'synclock', 'using', 'with'];\nvar middleKeywords = ['else','elseif','case', 'catch', 'finally'];\nvar endKeywords = ['next','loop'];\n\nvar operatorKeywords = ['and', \"andalso\", 'or', 'orelse', 'xor', 'in', 'not', 'is', 'isnot', 'like'];\nvar wordOperators = wordRegexp(operatorKeywords);\n\nvar commonKeywords = [\"#const\", \"#else\", \"#elseif\", \"#end\", \"#if\", \"#region\", \"addhandler\", \"addressof\", \"alias\", \"as\", \"byref\", \"byval\", \"cbool\", \"cbyte\", \"cchar\", \"cdate\", \"cdbl\", \"cdec\", \"cint\", \"clng\", \"cobj\", \"compare\", \"const\", \"continue\", \"csbyte\", \"cshort\", \"csng\", \"cstr\", \"cuint\", \"culng\", \"cushort\", \"declare\", \"default\", \"delegate\", \"dim\", \"directcast\", \"each\", \"erase\", \"error\", \"event\", \"exit\", \"explicit\", \"false\", \"for\", \"friend\", \"gettype\", \"goto\", \"handles\", \"implements\", \"imports\", \"infer\", \"inherits\", \"interface\", \"isfalse\", \"istrue\", \"lib\", \"me\", \"mod\", \"mustinherit\", \"mustoverride\", \"my\", \"mybase\", \"myclass\", \"namespace\", \"narrowing\", \"new\", \"nothing\", \"notinheritable\", \"notoverridable\", \"of\", \"off\", \"on\", \"operator\", \"option\", \"optional\", \"out\", \"overloads\", \"overridable\", \"overrides\", \"paramarray\", \"partial\", \"private\", \"protected\", \"public\", \"raiseevent\", \"readonly\", \"redim\", \"removehandler\", \"resume\", \"return\", \"shadows\", \"shared\", \"static\", \"step\", \"stop\", \"strict\", \"then\", \"throw\", \"to\", \"true\", \"trycast\", \"typeof\", \"until\", \"until\", \"when\", \"widening\", \"withevents\", \"writeonly\"];\n\nvar commontypes = ['object', 'boolean', 'char', 'string', 'byte', 'sbyte', 'short', 'ushort', 'int16', 'uint16', 'integer', 'uinteger', 'int32', 'uint32', 'long', 'ulong', 'int64', 'uint64', 'decimal', 'single', 'double', 'float', 'date', 'datetime', 'intptr', 'uintptr'];\n\nvar keywords = wordRegexp(commonKeywords);\nvar types = wordRegexp(commontypes);\nvar stringPrefixes = '\"';\n\nvar opening = wordRegexp(openingKeywords);\nvar middle = wordRegexp(middleKeywords);\nvar closing = wordRegexp(endKeywords);\nvar doubleClosing = wordRegexp(['end']);\nvar doOpening = wordRegexp(['do']);\n\nvar indentInfo = null;\n\nfunction indent(_stream, state) {\n state.currentIndent++;\n}\n\nfunction dedent(_stream, state) {\n state.currentIndent--;\n}\n// tokenizers\nfunction tokenBase(stream, state) {\n if (stream.eatSpace()) {\n return null;\n }\n\n var ch = stream.peek();\n\n // Handle Comments\n if (ch === \"'\") {\n stream.skipToEnd();\n return 'comment';\n }\n\n\n // Handle Number Literals\n if (stream.match(/^((&H)|(&O))?[0-9\\.a-f]/i, false)) {\n var floatLiteral = false;\n // Floats\n if (stream.match(/^\\d*\\.\\d+F?/i)) { floatLiteral = true; }\n else if (stream.match(/^\\d+\\.\\d*F?/)) { floatLiteral = true; }\n else if (stream.match(/^\\.\\d+F?/)) { floatLiteral = true; }\n\n if (floatLiteral) {\n // Float literals may be \"imaginary\"\n stream.eat(/J/i);\n return 'number';\n }\n // Integers\n var intLiteral = false;\n // Hex\n if (stream.match(/^&H[0-9a-f]+/i)) { intLiteral = true; }\n // Octal\n else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; }\n // Decimal\n else if (stream.match(/^[1-9]\\d*F?/)) {\n // Decimal literals may be \"imaginary\"\n stream.eat(/J/i);\n // TODO - Can you have imaginary longs?\n intLiteral = true;\n }\n // Zero by itself with no other piece of number.\n else if (stream.match(/^0(?![\\dx])/i)) { intLiteral = true; }\n if (intLiteral) {\n // Integer literals may be \"long\"\n stream.eat(/L/i);\n return 'number';\n }\n }\n\n // Handle Strings\n if (stream.match(stringPrefixes)) {\n state.tokenize = tokenStringFactory(stream.current());\n return state.tokenize(stream, state);\n }\n\n // Handle operators and Delimiters\n if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {\n return null;\n }\n if (stream.match(doubleOperators)\n || stream.match(singleOperators)\n || stream.match(wordOperators)) {\n return 'operator';\n }\n if (stream.match(singleDelimiters)) {\n return null;\n }\n if (stream.match(doOpening)) {\n indent(stream,state);\n state.doInCurrentLine = true;\n return 'keyword';\n }\n if (stream.match(opening)) {\n if (! state.doInCurrentLine)\n indent(stream,state);\n else\n state.doInCurrentLine = false;\n return 'keyword';\n }\n if (stream.match(middle)) {\n return 'keyword';\n }\n\n if (stream.match(doubleClosing)) {\n dedent(stream,state);\n dedent(stream,state);\n return 'keyword';\n }\n if (stream.match(closing)) {\n dedent(stream,state);\n return 'keyword';\n }\n\n if (stream.match(types)) {\n return 'keyword';\n }\n\n if (stream.match(keywords)) {\n return 'keyword';\n }\n\n if (stream.match(identifiers)) {\n return 'variable';\n }\n\n // Handle non-detected items\n stream.next();\n return ERRORCLASS;\n}\n\nfunction tokenStringFactory(delimiter) {\n var singleline = delimiter.length == 1;\n var OUTCLASS = 'string';\n\n return function(stream, state) {\n while (!stream.eol()) {\n stream.eatWhile(/[^'\"]/);\n if (stream.match(delimiter)) {\n state.tokenize = tokenBase;\n return OUTCLASS;\n } else {\n stream.eat(/['\"]/);\n }\n }\n if (singleline) {\n state.tokenize = tokenBase;\n }\n return OUTCLASS;\n };\n}\n\n\nfunction tokenLexer(stream, state) {\n var style = state.tokenize(stream, state);\n var current = stream.current();\n\n // Handle '.' connected identifiers\n if (current === '.') {\n style = state.tokenize(stream, state);\n if (style === 'variable') {\n return 'variable';\n } else {\n return ERRORCLASS;\n }\n }\n\n\n var delimiter_index = '[({'.indexOf(current);\n if (delimiter_index !== -1) {\n indent(stream, state );\n }\n if (indentInfo === 'dedent') {\n if (dedent(stream, state)) {\n return ERRORCLASS;\n }\n }\n delimiter_index = '])}'.indexOf(current);\n if (delimiter_index !== -1) {\n if (dedent(stream, state)) {\n return ERRORCLASS;\n }\n }\n\n return style;\n}\n\nexport const vb = {\n name: \"vb\",\n\n startState: function() {\n return {\n tokenize: tokenBase,\n lastToken: null,\n currentIndent: 0,\n nextLineIndent: 0,\n doInCurrentLine: false\n\n\n };\n },\n\n token: function(stream, state) {\n if (stream.sol()) {\n state.currentIndent += state.nextLineIndent;\n state.nextLineIndent = 0;\n state.doInCurrentLine = 0;\n }\n var style = tokenLexer(stream, state);\n\n state.lastToken = {style:style, content: stream.current()};\n\n\n\n return style;\n },\n\n indent: function(state, textAfter, cx) {\n var trueText = textAfter.replace(/^\\s+|\\s+$/g, '') ;\n if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return cx.unit*(state.currentIndent-1);\n if(state.currentIndent < 0) return 0;\n return state.currentIndent * cx.unit;\n },\n\n languageData: {\n closeBrackets: {brackets: [\"(\", \"[\", \"{\", '\"']},\n commentTokens: {line: \"'\"},\n autocomplete: openingKeywords.concat(middleKeywords).concat(endKeywords)\n .concat(operatorKeywords).concat(commonKeywords).concat(commontypes)\n }\n};\n"],"names":["ERRORCLASS","wordRegexp","words","RegExp","join","singleOperators","singleDelimiters","doubleOperators","doubleDelimiters","tripleDelimiters","identifiers","openingKeywords","middleKeywords","endKeywords","operatorKeywords","wordOperators","commonKeywords","commontypes","keywords","types","stringPrefixes","opening","middle","closing","doubleClosing","doOpening","indent","_stream","state","currentIndent","dedent","tokenBase","stream","eatSpace","delimiter","singleline","OUTCLASS","peek","skipToEnd","match","floatLiteral","eat","intLiteral","tokenize","current","length","eol","eatWhile","doInCurrentLine","next","vb","name","startState","lastToken","nextLineIndent","token","sol","style","delimiter_index","indexOf","tokenLexer","content","textAfter","cx","trueText","replace","unit","languageData","closeBrackets","brackets","commentTokens","line","autocomplete","concat"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/1803.index.js b/book/_build/html/_static/1803.index.js
new file mode 100644
index 0000000..ca9849c
--- /dev/null
+++ b/book/_build/html/_static/1803.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[1803],{21803:(t,a,e)=>{e.r(a),e.d(a,{troff:()=>h});var n={};function r(t){if(t.eatSpace())return null;var a=t.sol(),e=t.next();if("\\"===e)return t.match("fB")||t.match("fR")||t.match("fI")||t.match("u")||t.match("d")||t.match("%")||t.match("&")?"string":t.match("m[")?(t.skipTo("]"),t.next(),"string"):t.match("s+")||t.match("s-")?(t.eatWhile(/[\d-]/),"string"):t.match("(")||t.match("*(")?(t.eatWhile(/[\w-]/),"string"):"string";if(a&&("."===e||"'"===e)&&t.eat("\\")&&t.eat('"'))return t.skipToEnd(),"comment";if(a&&"."===e){if(t.match("B ")||t.match("I ")||t.match("R "))return"attribute";if(t.match("TH ")||t.match("SH ")||t.match("SS ")||t.match("HP "))return t.skipToEnd(),"quote";if(t.match(/[A-Z]/)&&t.match(/[A-Z]/)||t.match(/[a-z]/)&&t.match(/[a-z]/))return"attribute"}t.eatWhile(/[\w-]/);var r=t.current();return n.hasOwnProperty(r)?n[r]:null}function c(t,a){return(a.tokens[0]||r)(t,a)}const h={name:"troff",startState:function(){return{tokens:[]}},token:function(t,a){return c(t,a)}}}}]);
+//# sourceMappingURL=1803.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/1803.index.js.map b/book/_build/html/_static/1803.index.js.map
new file mode 100644
index 0000000..c961f6f
--- /dev/null
+++ b/book/_build/html/_static/1803.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"1803.index.js","mappings":"2HAAA,IAAIA,EAAQ,CAAC,EAEb,SAASC,EAAUC,GACjB,GAAIA,EAAOC,WAAY,OAAO,KAE9B,IAAIC,EAAMF,EAAOE,MACbC,EAAKH,EAAOI,OAEhB,GAAW,OAAPD,EACF,OAAIH,EAAOK,MAAM,OAASL,EAAOK,MAAM,OAASL,EAAOK,MAAM,OACzDL,EAAOK,MAAM,MAASL,EAAOK,MAAM,MACnCL,EAAOK,MAAM,MAASL,EAAOK,MAAM,KAC9B,SAELL,EAAOK,MAAM,OACfL,EAAOM,OAAO,KACdN,EAAOI,OACA,UAELJ,EAAOK,MAAM,OAASL,EAAOK,MAAM,OACrCL,EAAOO,SAAS,SACT,UAELP,EAAOK,MAAM,MAASL,EAAOK,MAAM,OACrCL,EAAOO,SAAS,SACT,UAEF,SAET,GAAIL,IAAe,MAAPC,GAAqB,MAAPA,IACpBH,EAAOQ,IAAI,OAASR,EAAOQ,IAAI,KAEjC,OADAR,EAAOS,YACA,UAGX,GAAIP,GAAc,MAAPC,EAAY,CACrB,GAAIH,EAAOK,MAAM,OAASL,EAAOK,MAAM,OAASL,EAAOK,MAAM,MAC3D,MAAO,YAET,GAAIL,EAAOK,MAAM,QAAUL,EAAOK,MAAM,QAAUL,EAAOK,MAAM,QAAUL,EAAOK,MAAM,OAEpF,OADAL,EAAOS,YACA,QAET,GAAKT,EAAOK,MAAM,UAAYL,EAAOK,MAAM,UAAcL,EAAOK,MAAM,UAAYL,EAAOK,MAAM,SAC7F,MAAO,WAEX,CACAL,EAAOO,SAAS,SAChB,IAAIG,EAAMV,EAAOW,UACjB,OAAOb,EAAMc,eAAeF,GAAOZ,EAAMY,GAAO,IAClD,CAEA,SAASG,EAASb,EAAQc,GACxB,OAAQA,EAAMC,OAAO,IAAMhB,GAAYC,EAAQc,EACjD,CAEO,MAAME,EAAQ,CACnBC,KAAM,QACNC,WAAY,WAAY,MAAO,CAACH,OAAO,GAAI,EAC3CI,MAAO,SAASnB,EAAQc,GACtB,OAAOD,EAASb,EAAQc,EAC1B,E","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/troff.js"],"sourcesContent":["var words = {};\n\nfunction tokenBase(stream) {\n if (stream.eatSpace()) return null;\n\n var sol = stream.sol();\n var ch = stream.next();\n\n if (ch === '\\\\') {\n if (stream.match('fB') || stream.match('fR') || stream.match('fI') ||\n stream.match('u') || stream.match('d') ||\n stream.match('%') || stream.match('&')) {\n return 'string';\n }\n if (stream.match('m[')) {\n stream.skipTo(']');\n stream.next();\n return 'string';\n }\n if (stream.match('s+') || stream.match('s-')) {\n stream.eatWhile(/[\\d-]/);\n return 'string';\n }\n if (stream.match('\\(') || stream.match('*\\(')) {\n stream.eatWhile(/[\\w-]/);\n return 'string';\n }\n return 'string';\n }\n if (sol && (ch === '.' || ch === '\\'')) {\n if (stream.eat('\\\\') && stream.eat('\\\"')) {\n stream.skipToEnd();\n return 'comment';\n }\n }\n if (sol && ch === '.') {\n if (stream.match('B ') || stream.match('I ') || stream.match('R ')) {\n return 'attribute';\n }\n if (stream.match('TH ') || stream.match('SH ') || stream.match('SS ') || stream.match('HP ')) {\n stream.skipToEnd();\n return 'quote';\n }\n if ((stream.match(/[A-Z]/) && stream.match(/[A-Z]/)) || (stream.match(/[a-z]/) && stream.match(/[a-z]/))) {\n return 'attribute';\n }\n }\n stream.eatWhile(/[\\w-]/);\n var cur = stream.current();\n return words.hasOwnProperty(cur) ? words[cur] : null;\n}\n\nfunction tokenize(stream, state) {\n return (state.tokens[0] || tokenBase) (stream, state);\n};\n\nexport const troff = {\n name: \"troff\",\n startState: function() {return {tokens:[]};},\n token: function(stream, state) {\n return tokenize(stream, state);\n }\n};\n"],"names":["words","tokenBase","stream","eatSpace","sol","ch","next","match","skipTo","eatWhile","eat","skipToEnd","cur","current","hasOwnProperty","tokenize","state","tokens","troff","name","startState","token"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/1814.index.js b/book/_build/html/_static/1814.index.js
new file mode 100644
index 0000000..ae0b933
--- /dev/null
+++ b/book/_build/html/_static/1814.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[1814],{81814:(e,t,n)=>{function a(e){for(var t={},n=0;n_});var i=a(["abstract","accept","allocatable","allocate","array","assign","asynchronous","backspace","bind","block","byte","call","case","class","close","common","contains","continue","cycle","data","deallocate","decode","deferred","dimension","do","elemental","else","encode","end","endif","entry","enumerator","equivalence","exit","external","extrinsic","final","forall","format","function","generic","go","goto","if","implicit","import","include","inquire","intent","interface","intrinsic","module","namelist","non_intrinsic","non_overridable","none","nopass","nullify","open","optional","options","parameter","pass","pause","pointer","print","private","program","protected","public","pure","read","recursive","result","return","rewind","save","select","sequence","stop","subroutine","target","then","to","type","use","value","volatile","where","while","write"]),r=a(["abort","abs","access","achar","acos","adjustl","adjustr","aimag","aint","alarm","all","allocated","alog","amax","amin","amod","and","anint","any","asin","associated","atan","besj","besjn","besy","besyn","bit_size","btest","cabs","ccos","ceiling","cexp","char","chdir","chmod","clog","cmplx","command_argument_count","complex","conjg","cos","cosh","count","cpu_time","cshift","csin","csqrt","ctime","c_funloc","c_loc","c_associated","c_null_ptr","c_null_funptr","c_f_pointer","c_null_char","c_alert","c_backspace","c_form_feed","c_new_line","c_carriage_return","c_horizontal_tab","c_vertical_tab","dabs","dacos","dasin","datan","date_and_time","dbesj","dbesj","dbesjn","dbesy","dbesy","dbesyn","dble","dcos","dcosh","ddim","derf","derfc","dexp","digits","dim","dint","dlog","dlog","dmax","dmin","dmod","dnint","dot_product","dprod","dsign","dsinh","dsin","dsqrt","dtanh","dtan","dtime","eoshift","epsilon","erf","erfc","etime","exit","exp","exponent","extends_type_of","fdate","fget","fgetc","float","floor","flush","fnum","fputc","fput","fraction","fseek","fstat","ftell","gerror","getarg","get_command","get_command_argument","get_environment_variable","getcwd","getenv","getgid","getlog","getpid","getuid","gmtime","hostnm","huge","iabs","iachar","iand","iargc","ibclr","ibits","ibset","ichar","idate","idim","idint","idnint","ieor","ierrno","ifix","imag","imagpart","index","int","ior","irand","isatty","ishft","ishftc","isign","iso_c_binding","is_iostat_end","is_iostat_eor","itime","kill","kind","lbound","len","len_trim","lge","lgt","link","lle","llt","lnblnk","loc","log","logical","long","lshift","lstat","ltime","matmul","max","maxexponent","maxloc","maxval","mclock","merge","move_alloc","min","minexponent","minloc","minval","mod","modulo","mvbits","nearest","new_line","nint","not","or","pack","perror","precision","present","product","radix","rand","random_number","random_seed","range","real","realpart","rename","repeat","reshape","rrspacing","rshift","same_type_as","scale","scan","second","selected_int_kind","selected_real_kind","set_exponent","shape","short","sign","signal","sinh","sin","sleep","sngl","spacing","spread","sqrt","srand","stat","sum","symlnk","system","system_clock","tan","tanh","time","tiny","transfer","transpose","trim","ttynam","ubound","umask","unlink","unpack","verify","xor","zabs","zcos","zexp","zlog","zsin","zsqrt"]),c=a(["c_bool","c_char","c_double","c_double_complex","c_float","c_float_complex","c_funptr","c_int","c_int16_t","c_int32_t","c_int64_t","c_int8_t","c_int_fast16_t","c_int_fast32_t","c_int_fast64_t","c_int_fast8_t","c_int_least16_t","c_int_least32_t","c_int_least64_t","c_int_least8_t","c_intmax_t","c_intptr_t","c_long","c_long_double","c_long_double_complex","c_long_long","c_ptr","c_short","c_signed_char","c_size_t","character","complex","double","integer","logical","real"]),o=/[+\-*&=<>\/\:]/,s=/^\.(and|or|eq|lt|le|gt|ge|ne|not|eqv|neqv)\./i;function l(e,t){if(e.match(s))return"operator";var n,a=e.next();if("!"==a)return e.skipToEnd(),"comment";if('"'==a||"'"==a)return t.tokenize=(n=a,function(e,t){for(var a,i=!1,r=!1;null!=(a=e.next());){if(a==n&&!i){r=!0;break}i=!i&&"\\"==a}return!r&&i||(t.tokenize=null),"string"}),t.tokenize(e,t);if(/[\[\]\(\),]/.test(a))return null;if(/\d/.test(a))return e.eatWhile(/[\w\.]/),"number";if(o.test(a))return e.eatWhile(o),"operator";e.eatWhile(/[\w\$_]/);var l=e.current().toLowerCase();return i.hasOwnProperty(l)?"keyword":r.hasOwnProperty(l)||c.hasOwnProperty(l)?"builtin":"variable"}const _={name:"fortran",startState:function(){return{tokenize:null}},token:function(e,t){return e.eatSpace()?null:(t.tokenize||l)(e,t)}}}}]);
+//# sourceMappingURL=1814.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/1814.index.js.map b/book/_build/html/_static/1814.index.js.map
new file mode 100644
index 0000000..46f64da
--- /dev/null
+++ b/book/_build/html/_static/1814.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"1814.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/fortran.js"],"sourcesContent":["function words(array) {\n var keys = {};\n for (var i = 0; i < array.length; ++i) {\n keys[array[i]] = true;\n }\n return keys;\n}\n\nvar keywords = words([\n \"abstract\", \"accept\", \"allocatable\", \"allocate\",\n \"array\", \"assign\", \"asynchronous\", \"backspace\",\n \"bind\", \"block\", \"byte\", \"call\", \"case\",\n \"class\", \"close\", \"common\", \"contains\",\n \"continue\", \"cycle\", \"data\", \"deallocate\",\n \"decode\", \"deferred\", \"dimension\", \"do\",\n \"elemental\", \"else\", \"encode\", \"end\",\n \"endif\", \"entry\", \"enumerator\", \"equivalence\",\n \"exit\", \"external\", \"extrinsic\", \"final\",\n \"forall\", \"format\", \"function\", \"generic\",\n \"go\", \"goto\", \"if\", \"implicit\", \"import\", \"include\",\n \"inquire\", \"intent\", \"interface\", \"intrinsic\",\n \"module\", \"namelist\", \"non_intrinsic\",\n \"non_overridable\", \"none\", \"nopass\",\n \"nullify\", \"open\", \"optional\", \"options\",\n \"parameter\", \"pass\", \"pause\", \"pointer\",\n \"print\", \"private\", \"program\", \"protected\",\n \"public\", \"pure\", \"read\", \"recursive\", \"result\",\n \"return\", \"rewind\", \"save\", \"select\", \"sequence\",\n \"stop\", \"subroutine\", \"target\", \"then\", \"to\", \"type\",\n \"use\", \"value\", \"volatile\", \"where\", \"while\",\n \"write\"]);\nvar builtins = words([\"abort\", \"abs\", \"access\", \"achar\", \"acos\",\n \"adjustl\", \"adjustr\", \"aimag\", \"aint\", \"alarm\",\n \"all\", \"allocated\", \"alog\", \"amax\", \"amin\",\n \"amod\", \"and\", \"anint\", \"any\", \"asin\",\n \"associated\", \"atan\", \"besj\", \"besjn\", \"besy\",\n \"besyn\", \"bit_size\", \"btest\", \"cabs\", \"ccos\",\n \"ceiling\", \"cexp\", \"char\", \"chdir\", \"chmod\",\n \"clog\", \"cmplx\", \"command_argument_count\",\n \"complex\", \"conjg\", \"cos\", \"cosh\", \"count\",\n \"cpu_time\", \"cshift\", \"csin\", \"csqrt\", \"ctime\",\n \"c_funloc\", \"c_loc\", \"c_associated\", \"c_null_ptr\",\n \"c_null_funptr\", \"c_f_pointer\", \"c_null_char\",\n \"c_alert\", \"c_backspace\", \"c_form_feed\",\n \"c_new_line\", \"c_carriage_return\",\n \"c_horizontal_tab\", \"c_vertical_tab\", \"dabs\",\n \"dacos\", \"dasin\", \"datan\", \"date_and_time\",\n \"dbesj\", \"dbesj\", \"dbesjn\", \"dbesy\", \"dbesy\",\n \"dbesyn\", \"dble\", \"dcos\", \"dcosh\", \"ddim\", \"derf\",\n \"derfc\", \"dexp\", \"digits\", \"dim\", \"dint\", \"dlog\",\n \"dlog\", \"dmax\", \"dmin\", \"dmod\", \"dnint\",\n \"dot_product\", \"dprod\", \"dsign\", \"dsinh\",\n \"dsin\", \"dsqrt\", \"dtanh\", \"dtan\", \"dtime\",\n \"eoshift\", \"epsilon\", \"erf\", \"erfc\", \"etime\",\n \"exit\", \"exp\", \"exponent\", \"extends_type_of\",\n \"fdate\", \"fget\", \"fgetc\", \"float\", \"floor\",\n \"flush\", \"fnum\", \"fputc\", \"fput\", \"fraction\",\n \"fseek\", \"fstat\", \"ftell\", \"gerror\", \"getarg\",\n \"get_command\", \"get_command_argument\",\n \"get_environment_variable\", \"getcwd\",\n \"getenv\", \"getgid\", \"getlog\", \"getpid\",\n \"getuid\", \"gmtime\", \"hostnm\", \"huge\", \"iabs\",\n \"iachar\", \"iand\", \"iargc\", \"ibclr\", \"ibits\",\n \"ibset\", \"ichar\", \"idate\", \"idim\", \"idint\",\n \"idnint\", \"ieor\", \"ierrno\", \"ifix\", \"imag\",\n \"imagpart\", \"index\", \"int\", \"ior\", \"irand\",\n \"isatty\", \"ishft\", \"ishftc\", \"isign\",\n \"iso_c_binding\", \"is_iostat_end\", \"is_iostat_eor\",\n \"itime\", \"kill\", \"kind\", \"lbound\", \"len\", \"len_trim\",\n \"lge\", \"lgt\", \"link\", \"lle\", \"llt\", \"lnblnk\", \"loc\",\n \"log\", \"logical\", \"long\", \"lshift\", \"lstat\", \"ltime\",\n \"matmul\", \"max\", \"maxexponent\", \"maxloc\", \"maxval\",\n \"mclock\", \"merge\", \"move_alloc\", \"min\", \"minexponent\",\n \"minloc\", \"minval\", \"mod\", \"modulo\", \"mvbits\",\n \"nearest\", \"new_line\", \"nint\", \"not\", \"or\", \"pack\",\n \"perror\", \"precision\", \"present\", \"product\", \"radix\",\n \"rand\", \"random_number\", \"random_seed\", \"range\",\n \"real\", \"realpart\", \"rename\", \"repeat\", \"reshape\",\n \"rrspacing\", \"rshift\", \"same_type_as\", \"scale\",\n \"scan\", \"second\", \"selected_int_kind\",\n \"selected_real_kind\", \"set_exponent\", \"shape\",\n \"short\", \"sign\", \"signal\", \"sinh\", \"sin\", \"sleep\",\n \"sngl\", \"spacing\", \"spread\", \"sqrt\", \"srand\", \"stat\",\n \"sum\", \"symlnk\", \"system\", \"system_clock\", \"tan\",\n \"tanh\", \"time\", \"tiny\", \"transfer\", \"transpose\",\n \"trim\", \"ttynam\", \"ubound\", \"umask\", \"unlink\",\n \"unpack\", \"verify\", \"xor\", \"zabs\", \"zcos\", \"zexp\",\n \"zlog\", \"zsin\", \"zsqrt\"]);\n\nvar dataTypes = words([\"c_bool\", \"c_char\", \"c_double\", \"c_double_complex\",\n \"c_float\", \"c_float_complex\", \"c_funptr\", \"c_int\",\n \"c_int16_t\", \"c_int32_t\", \"c_int64_t\", \"c_int8_t\",\n \"c_int_fast16_t\", \"c_int_fast32_t\", \"c_int_fast64_t\",\n \"c_int_fast8_t\", \"c_int_least16_t\", \"c_int_least32_t\",\n \"c_int_least64_t\", \"c_int_least8_t\", \"c_intmax_t\",\n \"c_intptr_t\", \"c_long\", \"c_long_double\",\n \"c_long_double_complex\", \"c_long_long\", \"c_ptr\",\n \"c_short\", \"c_signed_char\", \"c_size_t\", \"character\",\n \"complex\", \"double\", \"integer\", \"logical\", \"real\"]);\nvar isOperatorChar = /[+\\-*&=<>\\/\\:]/;\nvar litOperator = /^\\.(and|or|eq|lt|le|gt|ge|ne|not|eqv|neqv)\\./i;\n\nfunction tokenBase(stream, state) {\n\n if (stream.match(litOperator)){\n return 'operator';\n }\n\n var ch = stream.next();\n if (ch == \"!\") {\n stream.skipToEnd();\n return \"comment\";\n }\n if (ch == '\"' || ch == \"'\") {\n state.tokenize = tokenString(ch);\n return state.tokenize(stream, state);\n }\n if (/[\\[\\]\\(\\),]/.test(ch)) {\n return null;\n }\n if (/\\d/.test(ch)) {\n stream.eatWhile(/[\\w\\.]/);\n return \"number\";\n }\n if (isOperatorChar.test(ch)) {\n stream.eatWhile(isOperatorChar);\n return \"operator\";\n }\n stream.eatWhile(/[\\w\\$_]/);\n var word = stream.current().toLowerCase();\n\n if (keywords.hasOwnProperty(word)){\n return 'keyword';\n }\n if (builtins.hasOwnProperty(word) || dataTypes.hasOwnProperty(word)) {\n return 'builtin';\n }\n return \"variable\";\n}\n\nfunction tokenString(quote) {\n return function(stream, state) {\n var escaped = false, next, end = false;\n while ((next = stream.next()) != null) {\n if (next == quote && !escaped) {\n end = true;\n break;\n }\n escaped = !escaped && next == \"\\\\\";\n }\n if (end || !escaped) state.tokenize = null;\n return \"string\";\n };\n}\n\n// Interface\n\nexport const fortran = {\n name: \"fortran\",\n startState: function() {\n return {tokenize: null};\n },\n\n token: function(stream, state) {\n if (stream.eatSpace()) return null;\n var style = (state.tokenize || tokenBase)(stream, state);\n if (style == \"comment\" || style == \"meta\") return style;\n return style;\n }\n};\n\n"],"names":["words","array","keys","i","length","keywords","builtins","dataTypes","isOperatorChar","litOperator","tokenBase","stream","state","match","quote","ch","next","skipToEnd","tokenize","escaped","end","test","eatWhile","word","current","toLowerCase","hasOwnProperty","fortran","name","startState","token","eatSpace"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/192.index.js b/book/_build/html/_static/192.index.js
new file mode 100644
index 0000000..798af6f
--- /dev/null
+++ b/book/_build/html/_static/192.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[192],{40192:(e,n,t)=>{t.r(n),t.d(n,{fcl:()=>s});var r={term:!0,method:!0,accu:!0,rule:!0,then:!0,is:!0,and:!0,or:!0,if:!0,default:!0},o={var_input:!0,var_output:!0,fuzzify:!0,defuzzify:!0,function_block:!0,ruleblock:!0},i={end_ruleblock:!0,end_defuzzify:!0,end_function_block:!0,end_fuzzify:!0,end_var:!0},a={true:!0,false:!0,nan:!0,real:!0,min:!0,max:!0,cog:!0,cogs:!0},u=/[+\-*&^%:=<>!|\/]/;function c(e,n){var t=e.next();if(/[\d\.]/.test(t))return"."==t?e.match(/^[0-9]+([eE][\-+]?[0-9]+)?/):"0"==t?e.match(/^[xX][0-9a-fA-F]+/)||e.match(/^0[0-7]+/):e.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/),"number";if("/"==t||"("==t){if(e.eat("*"))return n.tokenize=l,l(e,n);if(e.eat("/"))return e.skipToEnd(),"comment"}if(u.test(t))return e.eatWhile(u),"operator";e.eatWhile(/[\w\$_\xa1-\uffff]/);var c=e.current().toLowerCase();return r.propertyIsEnumerable(c)||o.propertyIsEnumerable(c)||i.propertyIsEnumerable(c)?"keyword":a.propertyIsEnumerable(c)?"atom":"variable"}function l(e,n){for(var t,r=!1;t=e.next();){if(("/"==t||")"==t)&&r){n.tokenize=c;break}r="*"==t}return"comment"}function f(e,n,t,r,o){this.indented=e,this.column=n,this.type=t,this.align=r,this.prev=o}const s={name:"fcl",startState:function(e){return{tokenize:null,context:new f(-e,0,"top",!1),indented:0,startOfLine:!0}},token:function(e,n){var t=n.context;if(e.sol()&&(null==t.align&&(t.align=!1),n.indented=e.indentation(),n.startOfLine=!0),e.eatSpace())return null;var r=(n.tokenize||c)(e,n);if("comment"==r)return r;null==t.align&&(t.align=!0);var a=e.current().toLowerCase();return o.propertyIsEnumerable(a)?function(e,n,t){e.context=new f(e.indented,n,"end_block",null,e.context)}(n,e.column()):i.propertyIsEnumerable(a)&&function(e){e.context.prev&&("end_block"==e.context.type&&(e.indented=e.context.indented),e.context=e.context.prev)}(n),n.startOfLine=!1,r},indent:function(e,n,t){if(e.tokenize!=c&&null!=e.tokenize)return 0;var r=e.context,o=i.propertyIsEnumerable(n);return r.align?r.column+(o?0:1):r.indented+(o?0:t.unit)},languageData:{commentTokens:{line:"//",block:{open:"(*",close:"*)"}}}}}}]);
+//# sourceMappingURL=192.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/192.index.js.map b/book/_build/html/_static/192.index.js.map
new file mode 100644
index 0000000..0ca3fc6
--- /dev/null
+++ b/book/_build/html/_static/192.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"192.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/fcl.js"],"sourcesContent":["var keywords = {\n \"term\": true,\n \"method\": true, \"accu\": true,\n \"rule\": true, \"then\": true, \"is\": true, \"and\": true, \"or\": true,\n \"if\": true, \"default\": true\n};\n\nvar start_blocks = {\n \"var_input\": true,\n \"var_output\": true,\n \"fuzzify\": true,\n \"defuzzify\": true,\n \"function_block\": true,\n \"ruleblock\": true\n};\n\nvar end_blocks = {\n \"end_ruleblock\": true,\n \"end_defuzzify\": true,\n \"end_function_block\": true,\n \"end_fuzzify\": true,\n \"end_var\": true\n};\n\nvar atoms = {\n \"true\": true, \"false\": true, \"nan\": true,\n \"real\": true, \"min\": true, \"max\": true, \"cog\": true, \"cogs\": true\n};\n\nvar isOperatorChar = /[+\\-*&^%:=<>!|\\/]/;\n\nfunction tokenBase(stream, state) {\n var ch = stream.next();\n\n if (/[\\d\\.]/.test(ch)) {\n if (ch == \".\") {\n stream.match(/^[0-9]+([eE][\\-+]?[0-9]+)?/);\n } else if (ch == \"0\") {\n stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/);\n } else {\n stream.match(/^[0-9]*\\.?[0-9]*([eE][\\-+]?[0-9]+)?/);\n }\n return \"number\";\n }\n\n if (ch == \"/\" || ch == \"(\") {\n if (stream.eat(\"*\")) {\n state.tokenize = tokenComment;\n return tokenComment(stream, state);\n }\n if (stream.eat(\"/\")) {\n stream.skipToEnd();\n return \"comment\";\n }\n }\n if (isOperatorChar.test(ch)) {\n stream.eatWhile(isOperatorChar);\n return \"operator\";\n }\n stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n\n var cur = stream.current().toLowerCase();\n if (keywords.propertyIsEnumerable(cur) ||\n start_blocks.propertyIsEnumerable(cur) ||\n end_blocks.propertyIsEnumerable(cur)) {\n return \"keyword\";\n }\n if (atoms.propertyIsEnumerable(cur)) return \"atom\";\n return \"variable\";\n}\n\n\nfunction tokenComment(stream, state) {\n var maybeEnd = false, ch;\n while (ch = stream.next()) {\n if ((ch == \"/\" || ch == \")\") && maybeEnd) {\n state.tokenize = tokenBase;\n break;\n }\n maybeEnd = (ch == \"*\");\n }\n return \"comment\";\n}\n\nfunction Context(indented, column, type, align, prev) {\n this.indented = indented;\n this.column = column;\n this.type = type;\n this.align = align;\n this.prev = prev;\n}\n\nfunction pushContext(state, col, type) {\n return state.context = new Context(state.indented, col, type, null, state.context);\n}\n\nfunction popContext(state) {\n if (!state.context.prev) return;\n var t = state.context.type;\n if (t == \"end_block\")\n state.indented = state.context.indented;\n return state.context = state.context.prev;\n}\n\n// Interface\n\nexport const fcl = {\n name: \"fcl\",\n startState: function(indentUnit) {\n return {\n tokenize: null,\n context: new Context(-indentUnit, 0, \"top\", false),\n indented: 0,\n startOfLine: true\n };\n },\n\n token: function(stream, state) {\n var ctx = state.context;\n if (stream.sol()) {\n if (ctx.align == null) ctx.align = false;\n state.indented = stream.indentation();\n state.startOfLine = true;\n }\n if (stream.eatSpace()) return null;\n\n var style = (state.tokenize || tokenBase)(stream, state);\n if (style == \"comment\") return style;\n if (ctx.align == null) ctx.align = true;\n\n var cur = stream.current().toLowerCase();\n\n if (start_blocks.propertyIsEnumerable(cur)) pushContext(state, stream.column(), \"end_block\");\n else if (end_blocks.propertyIsEnumerable(cur)) popContext(state);\n\n state.startOfLine = false;\n return style;\n },\n\n indent: function(state, textAfter, cx) {\n if (state.tokenize != tokenBase && state.tokenize != null) return 0;\n var ctx = state.context;\n\n var closing = end_blocks.propertyIsEnumerable(textAfter);\n if (ctx.align) return ctx.column + (closing ? 0 : 1);\n else return ctx.indented + (closing ? 0 : cx.unit);\n },\n\n languageData: {\n commentTokens: {line: \"//\", block: {open: \"(*\", close: \"*)\"}}\n }\n};\n\n"],"names":["keywords","start_blocks","end_blocks","atoms","isOperatorChar","tokenBase","stream","state","ch","next","test","match","eat","tokenize","tokenComment","skipToEnd","eatWhile","cur","current","toLowerCase","propertyIsEnumerable","maybeEnd","Context","indented","column","type","align","prev","this","fcl","name","startState","indentUnit","context","startOfLine","token","ctx","sol","indentation","eatSpace","style","col","pushContext","popContext","indent","textAfter","cx","closing","unit","languageData","commentTokens","line","block","open","close"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/2123.index.js b/book/_build/html/_static/2123.index.js
new file mode 100644
index 0000000..8763a24
--- /dev/null
+++ b/book/_build/html/_static/2123.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[2123],{42123:(e,t,i)=>{i.r(t),i.d(t,{yaml:()=>a});var r=new RegExp("\\b(("+["true","false","on","off","yes","no"].join(")|(")+"))$","i");const a={name:"yaml",token:function(e,t){var i=e.peek(),a=t.escaped;if(t.escaped=!1,"#"==i&&(0==e.pos||/\s/.test(e.string.charAt(e.pos-1))))return e.skipToEnd(),"comment";if(e.match(/^('([^']|\\.)*'?|"([^"]|\\.)*"?)/))return"string";if(t.literal&&e.indentation()>t.keyCol)return e.skipToEnd(),"string";if(t.literal&&(t.literal=!1),e.sol()){if(t.keyCol=0,t.pair=!1,t.pairStart=!1,e.match("---"))return"def";if(e.match("..."))return"def";if(e.match(/^\s*-\s+/))return"meta"}if(e.match(/^(\{|\}|\[|\])/))return"{"==i?t.inlinePairs++:"}"==i?t.inlinePairs--:"["==i?t.inlineList++:t.inlineList--,"meta";if(t.inlineList>0&&!a&&","==i)return e.next(),"meta";if(t.inlinePairs>0&&!a&&","==i)return t.keyCol=0,t.pair=!1,t.pairStart=!1,e.next(),"meta";if(t.pairStart){if(e.match(/^\s*(\||\>)\s*/))return t.literal=!0,"meta";if(e.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i))return"variable";if(0==t.inlinePairs&&e.match(/^\s*-?[0-9\.\,]+\s?$/))return"number";if(t.inlinePairs>0&&e.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/))return"number";if(e.match(r))return"keyword"}return!t.pair&&e.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)?(t.pair=!0,t.keyCol=e.indentation(),"atom"):t.pair&&e.match(/^:\s*/)?(t.pairStart=!0,"meta"):(t.pairStart=!1,t.escaped="\\"==i,e.next(),null)},startState:function(){return{pair:!1,pairStart:!1,keyCol:0,inlinePairs:0,inlineList:0,literal:!1,escaped:!1}},languageData:{commentTokens:{line:"#"}}}}}]);
+//# sourceMappingURL=2123.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/2123.index.js.map b/book/_build/html/_static/2123.index.js.map
new file mode 100644
index 0000000..223a880
--- /dev/null
+++ b/book/_build/html/_static/2123.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"2123.index.js","mappings":"0HAAA,IACIA,EAAe,IAAIC,OAAO,QADnB,CAAC,OAAQ,QAAS,KAAM,MAAO,MAAO,MACNC,KAAK,OAAO,MAAO,KAEvD,MAAMC,EAAO,CAClBC,KAAM,OACNC,MAAO,SAASC,EAAQC,GACtB,IAAIC,EAAKF,EAAOG,OACZC,EAAMH,EAAMI,QAGhB,GAFAJ,EAAMI,SAAU,EAEN,KAANH,IAA4B,GAAdF,EAAOM,KAAY,KAAKC,KAAKP,EAAOQ,OAAOC,OAAOT,EAAOM,IAAM,KAE/E,OADAN,EAAOU,YACA,UAGT,GAAIV,EAAOW,MAAM,oCACf,MAAO,SAET,GAAIV,EAAMW,SAAWZ,EAAOa,cAAgBZ,EAAMa,OAC5B,OAApBd,EAAOU,YAAoB,SAE7B,GADWT,EAAMW,UAAWX,EAAMW,SAAU,GACxCZ,EAAOe,MAAO,CAKhB,GAJAd,EAAMa,OAAS,EACfb,EAAMe,MAAO,EACbf,EAAMgB,WAAY,EAEfjB,EAAOW,MAAM,OAAU,MAAO,MAEjC,GAAIX,EAAOW,MAAM,OAAU,MAAO,MAElC,GAAIX,EAAOW,MAAM,YAAe,MAAO,MACzC,CAEA,GAAIX,EAAOW,MAAM,kBASf,MARU,KAANT,EACFD,EAAMiB,cACO,KAANhB,EACPD,EAAMiB,cACO,KAANhB,EACPD,EAAMkB,aAENlB,EAAMkB,aACD,OAIT,GAAIlB,EAAMkB,WAAa,IAAMf,GAAa,KAANF,EAElC,OADAF,EAAOoB,OACA,OAGT,GAAInB,EAAMiB,YAAc,IAAMd,GAAa,KAANF,EAKnC,OAJAD,EAAMa,OAAS,EACfb,EAAMe,MAAO,EACbf,EAAMgB,WAAY,EAClBjB,EAAOoB,OACA,OAIT,GAAInB,EAAMgB,UAAW,CAEnB,GAAIjB,EAAOW,MAAM,kBAA2C,OAAtBV,EAAMW,SAAU,EAAa,OAEnE,GAAIZ,EAAOW,MAAM,+BAAkC,MAAO,WAE1D,GAAyB,GAArBV,EAAMiB,aAAoBlB,EAAOW,MAAM,wBAA2B,MAAO,SAC7E,GAAIV,EAAMiB,YAAc,GAAKlB,EAAOW,MAAM,gCAAmC,MAAO,SAEpF,GAAIX,EAAOW,MAAMjB,GAAiB,MAAO,SAC3C,CAGA,OAAKO,EAAMe,MAAQhB,EAAOW,MAAM,kFAC9BV,EAAMe,MAAO,EACbf,EAAMa,OAASd,EAAOa,cACf,QAELZ,EAAMe,MAAQhB,EAAOW,MAAM,UAAYV,EAAMgB,WAAY,EAAa,SAG1EhB,EAAMgB,WAAY,EAClBhB,EAAMI,QAAiB,MAANH,EACjBF,EAAOoB,OACA,KACT,EACAC,WAAY,WACV,MAAO,CACLL,MAAM,EACNC,WAAW,EACXH,OAAQ,EACRI,YAAa,EACbC,WAAY,EACZP,SAAS,EACTP,SAAS,EAEb,EACAiB,aAAc,CACZC,cAAe,CAACC,KAAM,M","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/yaml.js"],"sourcesContent":["var cons = ['true', 'false', 'on', 'off', 'yes', 'no'];\nvar keywordRegex = new RegExp(\"\\\\b((\"+cons.join(\")|(\")+\"))$\", 'i');\n\nexport const yaml = {\n name: \"yaml\",\n token: function(stream, state) {\n var ch = stream.peek();\n var esc = state.escaped;\n state.escaped = false;\n /* comments */\n if (ch == \"#\" && (stream.pos == 0 || /\\s/.test(stream.string.charAt(stream.pos - 1)))) {\n stream.skipToEnd();\n return \"comment\";\n }\n\n if (stream.match(/^('([^']|\\\\.)*'?|\"([^\"]|\\\\.)*\"?)/))\n return \"string\";\n\n if (state.literal && stream.indentation() > state.keyCol) {\n stream.skipToEnd(); return \"string\";\n } else if (state.literal) { state.literal = false; }\n if (stream.sol()) {\n state.keyCol = 0;\n state.pair = false;\n state.pairStart = false;\n /* document start */\n if(stream.match('---')) { return \"def\"; }\n /* document end */\n if (stream.match('...')) { return \"def\"; }\n /* array list item */\n if (stream.match(/^\\s*-\\s+/)) { return 'meta'; }\n }\n /* inline pairs/lists */\n if (stream.match(/^(\\{|\\}|\\[|\\])/)) {\n if (ch == '{')\n state.inlinePairs++;\n else if (ch == '}')\n state.inlinePairs--;\n else if (ch == '[')\n state.inlineList++;\n else\n state.inlineList--;\n return 'meta';\n }\n\n /* list separator */\n if (state.inlineList > 0 && !esc && ch == ',') {\n stream.next();\n return 'meta';\n }\n /* pairs separator */\n if (state.inlinePairs > 0 && !esc && ch == ',') {\n state.keyCol = 0;\n state.pair = false;\n state.pairStart = false;\n stream.next();\n return 'meta';\n }\n\n /* start of value of a pair */\n if (state.pairStart) {\n /* block literals */\n if (stream.match(/^\\s*(\\||\\>)\\s*/)) { state.literal = true; return 'meta'; };\n /* references */\n if (stream.match(/^\\s*(\\&|\\*)[a-z0-9\\._-]+\\b/i)) { return 'variable'; }\n /* numbers */\n if (state.inlinePairs == 0 && stream.match(/^\\s*-?[0-9\\.\\,]+\\s?$/)) { return 'number'; }\n if (state.inlinePairs > 0 && stream.match(/^\\s*-?[0-9\\.\\,]+\\s?(?=(,|}))/)) { return 'number'; }\n /* keywords */\n if (stream.match(keywordRegex)) { return 'keyword'; }\n }\n\n /* pairs (associative arrays) -> key */\n if (!state.pair && stream.match(/^\\s*(?:[,\\[\\]{}&*!|>'\"%@`][^\\s'\":]|[^,\\[\\]{}#&*!|>'\"%@`])[^#]*?(?=\\s*:($|\\s))/)) {\n state.pair = true;\n state.keyCol = stream.indentation();\n return \"atom\";\n }\n if (state.pair && stream.match(/^:\\s*/)) { state.pairStart = true; return 'meta'; }\n\n /* nothing found, continue */\n state.pairStart = false;\n state.escaped = (ch == '\\\\');\n stream.next();\n return null;\n },\n startState: function() {\n return {\n pair: false,\n pairStart: false,\n keyCol: 0,\n inlinePairs: 0,\n inlineList: 0,\n literal: false,\n escaped: false\n };\n },\n languageData: {\n commentTokens: {line: \"#\"}\n }\n};\n"],"names":["keywordRegex","RegExp","join","yaml","name","token","stream","state","ch","peek","esc","escaped","pos","test","string","charAt","skipToEnd","match","literal","indentation","keyCol","sol","pair","pairStart","inlinePairs","inlineList","next","startState","languageData","commentTokens","line"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/2155.index.js b/book/_build/html/_static/2155.index.js
new file mode 100644
index 0000000..a690748
--- /dev/null
+++ b/book/_build/html/_static/2155.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[2155],{2155:(e,n,t)=>{t.r(n),t.d(n,{dockerFile:()=>k});var r=t(74391),a="from",o=new RegExp("^(\\s*)\\b("+a+")\\b","i"),s=["run","cmd","entrypoint","shell"],l=new RegExp("^(\\s*)("+s.join("|")+")(\\s+\\[)","i"),i="expose",u=new RegExp("^(\\s*)("+i+")(\\s+)","i"),g="("+[a,i].concat(s).concat(["arg","from","maintainer","label","env","add","copy","volume","user","workdir","onbuild","stopsignal","healthcheck","shell"]).join("|")+")",d=new RegExp("^(\\s*)"+g+"(\\s*)(#.*)?$","i"),x=new RegExp("^(\\s*)"+g+"(\\s+)","i");const k=(0,r.Q)({start:[{regex:/^\s*#.*$/,sol:!0,token:"comment"},{regex:o,token:[null,"keyword"],sol:!0,next:"from"},{regex:d,token:[null,"keyword",null,"error"],sol:!0},{regex:l,token:[null,"keyword",null],sol:!0,next:"array"},{regex:u,token:[null,"keyword",null],sol:!0,next:"expose"},{regex:x,token:[null,"keyword",null],sol:!0,next:"arguments"},{regex:/./,token:null}],from:[{regex:/\s*$/,token:null,next:"start"},{regex:/(\s*)(#.*)$/,token:[null,"error"],next:"start"},{regex:/(\s*\S+\s+)(as)/i,token:[null,"keyword"],next:"start"},{token:null,next:"start"}],single:[{regex:/(?:[^\\']|\\.)/,token:"string"},{regex:/'/,token:"string",pop:!0}],double:[{regex:/(?:[^\\"]|\\.)/,token:"string"},{regex:/"/,token:"string",pop:!0}],array:[{regex:/\]/,token:null,next:"start"},{regex:/"(?:[^\\"]|\\.)*"?/,token:"string"}],expose:[{regex:/\d+$/,token:"number",next:"start"},{regex:/[^\d]+$/,token:null,next:"start"},{regex:/\d+/,token:"number"},{regex:/[^\d]+/,token:null},{token:null,next:"start"}],arguments:[{regex:/^\s*#.*$/,sol:!0,token:"comment"},{regex:/"(?:[^\\"]|\\.)*"?$/,token:"string",next:"start"},{regex:/"/,token:"string",push:"double"},{regex:/'(?:[^\\']|\\.)*'?$/,token:"string",next:"start"},{regex:/'/,token:"string",push:"single"},{regex:/[^#"']+[\\`]$/,token:null},{regex:/[^#"']+$/,token:null,next:"start"},{regex:/[^#"']+/,token:null},{token:null,next:"start"}],languageData:{commentTokens:{line:"#"}}})},74391:(e,n,t)=>{function r(e){a(e,"start");var n={},t=e.languageData||{},r=!1;for(var i in e)if(i!=t&&e.hasOwnProperty(i))for(var u=n[i]=[],g=e[i],d=0;d2&&s.token&&"string"!=typeof s.token){t.pending=[];for(var u=2;u-1)return null;var a=t.indent.length-1,o=e[t.state];e:for(;;){for(var s=0;sr})}}]);
+//# sourceMappingURL=2155.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/2155.index.js.map b/book/_build/html/_static/2155.index.js.map
new file mode 100644
index 0000000..fca09fd
--- /dev/null
+++ b/book/_build/html/_static/2155.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"2155.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/dockerfile.js","webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/simple-mode.js"],"sourcesContent":["import {simpleMode} from \"./simple-mode.js\"\n\nvar from = \"from\";\nvar fromRegex = new RegExp(\"^(\\\\s*)\\\\b(\" + from + \")\\\\b\", \"i\");\n\nvar shells = [\"run\", \"cmd\", \"entrypoint\", \"shell\"];\nvar shellsAsArrayRegex = new RegExp(\"^(\\\\s*)(\" + shells.join('|') + \")(\\\\s+\\\\[)\", \"i\");\n\nvar expose = \"expose\";\nvar exposeRegex = new RegExp(\"^(\\\\s*)(\" + expose + \")(\\\\s+)\", \"i\");\n\nvar others = [\n \"arg\", \"from\", \"maintainer\", \"label\", \"env\",\n \"add\", \"copy\", \"volume\", \"user\",\n \"workdir\", \"onbuild\", \"stopsignal\", \"healthcheck\", \"shell\"\n];\n\n// Collect all Dockerfile directives\nvar instructions = [from, expose].concat(shells).concat(others),\n instructionRegex = \"(\" + instructions.join('|') + \")\",\n instructionOnlyLine = new RegExp(\"^(\\\\s*)\" + instructionRegex + \"(\\\\s*)(#.*)?$\", \"i\"),\n instructionWithArguments = new RegExp(\"^(\\\\s*)\" + instructionRegex + \"(\\\\s+)\", \"i\");\n\nexport const dockerFile = simpleMode({\n start: [\n // Block comment: This is a line starting with a comment\n {\n regex: /^\\s*#.*$/,\n sol: true,\n token: \"comment\"\n },\n {\n regex: fromRegex,\n token: [null, \"keyword\"],\n sol: true,\n next: \"from\"\n },\n // Highlight an instruction without any arguments (for convenience)\n {\n regex: instructionOnlyLine,\n token: [null, \"keyword\", null, \"error\"],\n sol: true\n },\n {\n regex: shellsAsArrayRegex,\n token: [null, \"keyword\", null],\n sol: true,\n next: \"array\"\n },\n {\n regex: exposeRegex,\n token: [null, \"keyword\", null],\n sol: true,\n next: \"expose\"\n },\n // Highlight an instruction followed by arguments\n {\n regex: instructionWithArguments,\n token: [null, \"keyword\", null],\n sol: true,\n next: \"arguments\"\n },\n {\n regex: /./,\n token: null\n }\n ],\n from: [\n {\n regex: /\\s*$/,\n token: null,\n next: \"start\"\n },\n {\n // Line comment without instruction arguments is an error\n regex: /(\\s*)(#.*)$/,\n token: [null, \"error\"],\n next: \"start\"\n },\n {\n regex: /(\\s*\\S+\\s+)(as)/i,\n token: [null, \"keyword\"],\n next: \"start\"\n },\n // Fail safe return to start\n {\n token: null,\n next: \"start\"\n }\n ],\n single: [\n {\n regex: /(?:[^\\\\']|\\\\.)/,\n token: \"string\"\n },\n {\n regex: /'/,\n token: \"string\",\n pop: true\n }\n ],\n double: [\n {\n regex: /(?:[^\\\\\"]|\\\\.)/,\n token: \"string\"\n },\n {\n regex: /\"/,\n token: \"string\",\n pop: true\n }\n ],\n array: [\n {\n regex: /\\]/,\n token: null,\n next: \"start\"\n },\n {\n regex: /\"(?:[^\\\\\"]|\\\\.)*\"?/,\n token: \"string\"\n }\n ],\n expose: [\n {\n regex: /\\d+$/,\n token: \"number\",\n next: \"start\"\n },\n {\n regex: /[^\\d]+$/,\n token: null,\n next: \"start\"\n },\n {\n regex: /\\d+/,\n token: \"number\"\n },\n {\n regex: /[^\\d]+/,\n token: null\n },\n // Fail safe return to start\n {\n token: null,\n next: \"start\"\n }\n ],\n arguments: [\n {\n regex: /^\\s*#.*$/,\n sol: true,\n token: \"comment\"\n },\n {\n regex: /\"(?:[^\\\\\"]|\\\\.)*\"?$/,\n token: \"string\",\n next: \"start\"\n },\n {\n regex: /\"/,\n token: \"string\",\n push: \"double\"\n },\n {\n regex: /'(?:[^\\\\']|\\\\.)*'?$/,\n token: \"string\",\n next: \"start\"\n },\n {\n regex: /'/,\n token: \"string\",\n push: \"single\"\n },\n {\n regex: /[^#\"']+[\\\\`]$/,\n token: null\n },\n {\n regex: /[^#\"']+$/,\n token: null,\n next: \"start\"\n },\n {\n regex: /[^#\"']+/,\n token: null\n },\n // Fail safe return to start\n {\n token: null,\n next: \"start\"\n }\n ],\n languageData: {\n commentTokens: {line: \"#\"}\n }\n});\n\n","export function simpleMode(states) {\n ensureState(states, \"start\");\n var states_ = {}, meta = states.languageData || {}, hasIndentation = false;\n for (var state in states) if (state != meta && states.hasOwnProperty(state)) {\n var list = states_[state] = [], orig = states[state];\n for (var i = 0; i < orig.length; i++) {\n var data = orig[i];\n list.push(new Rule(data, states));\n if (data.indent || data.dedent) hasIndentation = true;\n }\n }\n return {\n name: meta.name,\n startState: function() {\n return {state: \"start\", pending: null, indent: hasIndentation ? [] : null};\n },\n copyState: function(state) {\n var s = {state: state.state, pending: state.pending, indent: state.indent && state.indent.slice(0)};\n if (state.stack)\n s.stack = state.stack.slice(0);\n return s;\n },\n token: tokenFunction(states_),\n indent: indentFunction(states_, meta),\n languageData: meta\n }\n};\n\nfunction ensureState(states, name) {\n if (!states.hasOwnProperty(name))\n throw new Error(\"Undefined state \" + name + \" in simple mode\");\n}\n\nfunction toRegex(val, caret) {\n if (!val) return /(?:)/;\n var flags = \"\";\n if (val instanceof RegExp) {\n if (val.ignoreCase) flags = \"i\";\n val = val.source;\n } else {\n val = String(val);\n }\n return new RegExp((caret === false ? \"\" : \"^\") + \"(?:\" + val + \")\", flags);\n}\n\nfunction asToken(val) {\n if (!val) return null;\n if (val.apply) return val\n if (typeof val == \"string\") return val.replace(/\\./g, \" \");\n var result = [];\n for (var i = 0; i < val.length; i++)\n result.push(val[i] && val[i].replace(/\\./g, \" \"));\n return result;\n}\n\nfunction Rule(data, states) {\n if (data.next || data.push) ensureState(states, data.next || data.push);\n this.regex = toRegex(data.regex);\n this.token = asToken(data.token);\n this.data = data;\n}\n\nfunction tokenFunction(states) {\n return function(stream, state) {\n if (state.pending) {\n var pend = state.pending.shift();\n if (state.pending.length == 0) state.pending = null;\n stream.pos += pend.text.length;\n return pend.token;\n }\n\n var curState = states[state.state];\n for (var i = 0; i < curState.length; i++) {\n var rule = curState[i];\n var matches = (!rule.data.sol || stream.sol()) && stream.match(rule.regex);\n if (matches) {\n if (rule.data.next) {\n state.state = rule.data.next;\n } else if (rule.data.push) {\n (state.stack || (state.stack = [])).push(state.state);\n state.state = rule.data.push;\n } else if (rule.data.pop && state.stack && state.stack.length) {\n state.state = state.stack.pop();\n }\n\n if (rule.data.indent)\n state.indent.push(stream.indentation() + stream.indentUnit);\n if (rule.data.dedent)\n state.indent.pop();\n var token = rule.token\n if (token && token.apply) token = token(matches)\n if (matches.length > 2 && rule.token && typeof rule.token != \"string\") {\n state.pending = [];\n for (var j = 2; j < matches.length; j++)\n if (matches[j])\n state.pending.push({text: matches[j], token: rule.token[j - 1]});\n stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));\n return token[0];\n } else if (token && token.join) {\n return token[0];\n } else {\n return token;\n }\n }\n }\n stream.next();\n return null;\n };\n}\n\nfunction indentFunction(states, meta) {\n return function(state, textAfter) {\n if (state.indent == null || meta.dontIndentStates && meta.doneIndentState.indexOf(state.state) > -1)\n return null\n\n var pos = state.indent.length - 1, rules = states[state.state];\n scan: for (;;) {\n for (var i = 0; i < rules.length; i++) {\n var rule = rules[i];\n if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {\n var m = rule.regex.exec(textAfter);\n if (m && m[0]) {\n pos--;\n if (rule.next || rule.push) rules = states[rule.next || rule.push];\n textAfter = textAfter.slice(m[0].length);\n continue scan;\n }\n }\n }\n break;\n }\n return pos < 0 ? 0 : state.indent[pos];\n };\n}\n"],"names":["from","fromRegex","RegExp","shells","shellsAsArrayRegex","join","expose","exposeRegex","instructionRegex","concat","instructionOnlyLine","instructionWithArguments","dockerFile","start","regex","sol","token","next","single","pop","double","array","arguments","push","languageData","commentTokens","line","simpleMode","states","ensureState","states_","meta","hasIndentation","state","hasOwnProperty","list","orig","i","length","data","Rule","indent","dedent","name","startState","pending","copyState","s","slice","stack","tokenFunction","indentFunction","Error","this","val","caret","flags","ignoreCase","source","String","toRegex","apply","replace","result","asToken","stream","pend","shift","pos","text","curState","rule","matches","match","indentation","indentUnit","j","backUp","textAfter","dontIndentStates","doneIndentState","indexOf","rules","scan","dedentIfLineStart","m","exec"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/2187.index.js b/book/_build/html/_static/2187.index.js
new file mode 100644
index 0000000..3e1b99a
--- /dev/null
+++ b/book/_build/html/_static/2187.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[2187],{32187:(e,t,n)=>{n.r(t),n.d(t,{brainfuck:()=>m});var o="><+-.,[]".split("");const m={name:"brainfuck",startState:function(){return{commentLine:!1,left:0,right:0,commentLoop:!1}},token:function(e,t){if(e.eatSpace())return null;e.sol()&&(t.commentLine=!1);var n=e.next().toString();return-1===o.indexOf(n)?(t.commentLine=!0,e.eol()&&(t.commentLine=!1),"comment"):!0===t.commentLine?(e.eol()&&(t.commentLine=!1),"comment"):"]"===n||"["===n?("["===n?t.left++:t.right++,"bracket"):"+"===n||"-"===n?"keyword":"<"===n||">"===n?"atom":"."===n||","===n?"def":void(e.eol()&&(t.commentLine=!1))}}}}]);
+//# sourceMappingURL=2187.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/2187.index.js.map b/book/_build/html/_static/2187.index.js.map
new file mode 100644
index 0000000..3135195
--- /dev/null
+++ b/book/_build/html/_static/2187.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"2187.index.js","mappings":"+HAAA,IAAIA,EAAU,WAAWC,MAAM,IAcxB,MAAMC,EAAY,CACvBC,KAAM,YACNC,WAAY,WACV,MAAO,CACLC,aAAa,EACbC,KAAM,EACNC,MAAO,EACPC,aAAa,EAEjB,EACAC,MAAO,SAASC,EAAQC,GACtB,GAAID,EAAOE,WAAY,OAAO,KAC3BF,EAAOG,QACRF,EAAMN,aAAc,GAEtB,IAAIS,EAAKJ,EAAOK,OAAOC,WACvB,OAA4B,IAAzBhB,EAAQiB,QAAQH,IA2BjBH,EAAMN,aAAc,EACjBK,EAAOQ,QACRP,EAAMN,aAAc,GAEf,YA9BkB,IAAtBM,EAAMN,aACJK,EAAOQ,QACRP,EAAMN,aAAc,GAEf,WAEC,MAAPS,GAAqB,MAAPA,GACL,MAAPA,EACDH,EAAML,OAGNK,EAAMJ,QAED,WAEM,MAAPO,GAAqB,MAAPA,EACb,UAEM,MAAPA,GAAqB,MAAPA,EACb,OAEM,MAAPA,GAAqB,MAAPA,EACb,WAURJ,EAAOQ,QACRP,EAAMN,aAAc,GAExB,E","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/brainfuck.js"],"sourcesContent":["var reserve = \"><+-.,[]\".split(\"\");\n/*\n comments can be either:\n placed behind lines\n\n +++ this is a comment\n\n where reserved characters cannot be used\n or in a loop\n [\n this is ok to use [ ] and stuff\n ]\n or preceded by #\n*/\nexport const brainfuck = {\n name: \"brainfuck\",\n startState: function() {\n return {\n commentLine: false,\n left: 0,\n right: 0,\n commentLoop: false\n }\n },\n token: function(stream, state) {\n if (stream.eatSpace()) return null\n if(stream.sol()){\n state.commentLine = false;\n }\n var ch = stream.next().toString();\n if(reserve.indexOf(ch) !== -1){\n if(state.commentLine === true){\n if(stream.eol()){\n state.commentLine = false;\n }\n return \"comment\";\n }\n if(ch === \"]\" || ch === \"[\"){\n if(ch === \"[\"){\n state.left++;\n }\n else{\n state.right++;\n }\n return \"bracket\";\n }\n else if(ch === \"+\" || ch === \"-\"){\n return \"keyword\";\n }\n else if(ch === \"<\" || ch === \">\"){\n return \"atom\";\n }\n else if(ch === \".\" || ch === \",\"){\n return \"def\";\n }\n }\n else{\n state.commentLine = true;\n if(stream.eol()){\n state.commentLine = false;\n }\n return \"comment\";\n }\n if(stream.eol()){\n state.commentLine = false;\n }\n }\n};\n"],"names":["reserve","split","brainfuck","name","startState","commentLine","left","right","commentLoop","token","stream","state","eatSpace","sol","ch","next","toString","indexOf","eol"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/22.index.js b/book/_build/html/_static/22.index.js
new file mode 100644
index 0000000..befb168
--- /dev/null
+++ b/book/_build/html/_static/22.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[22],{22:(e,t,n)=>{function r(e){for(var t={},n=e.split(" "),r=0;rv});var i,a=r("abstract as assert boolean break byte case catch char class const continue def default do double else enum extends final finally float for goto if implements import in instanceof int interface long native new package private protected public return short static strictfp super switch synchronized threadsafe throw throws trait transient try void volatile while"),o=r("catch class def do else enum finally for if interface switch trait try while"),l=r("return break continue"),s=r("null true false this");function u(e,t){var n=e.next();if('"'==n||"'"==n)return c(n,e,t);if(/[\[\]{}\(\),;\:\.]/.test(n))return i=n,null;if(/\d/.test(n))return e.eatWhile(/[\w\.]/),e.eat(/eE/)&&(e.eat(/\+\-/),e.eatWhile(/\d/)),"number";if("/"==n){if(e.eat("*"))return t.tokenize.push(k),k(e,t);if(e.eat("/"))return e.skipToEnd(),"comment";if(m(t.lastToken,!1))return c(n,e,t)}if("-"==n&&e.eat(">"))return i="->",null;if(/[+\-*&%=<>!?|\/~]/.test(n))return e.eatWhile(/[+\-*&%=<>|~]/),"operator";if(e.eatWhile(/[\w\$_]/),"@"==n)return e.eatWhile(/[\w\$_\.]/),"meta";if("."==t.lastToken)return"property";if(e.eat(":"))return i="proplabel","property";var r=e.current();return s.propertyIsEnumerable(r)?"atom":a.propertyIsEnumerable(r)?(o.propertyIsEnumerable(r)?i="newstatement":l.propertyIsEnumerable(r)&&(i="standalone"),"keyword"):"variable"}function c(e,t,n){var r=!1;if("/"!=e&&t.eat(e)){if(!t.eat(e))return"string";r=!0}function i(t,n){for(var i,a=!1,o=!r;null!=(i=t.next());){if(i==e&&!a){if(!r)break;if(t.match(e+e)){o=!0;break}}if('"'==e&&"$"==i&&!a){if(t.eat("{"))return n.tokenize.push(f()),"string";if(t.match(/^\w/,!1))return n.tokenize.push(p),"string"}a=!a&&"\\"==i}return o&&n.tokenize.pop(),"string"}return n.tokenize.push(i),i(t,n)}function f(){var e=1;function t(t,n){if("}"==t.peek()){if(0==--e)return n.tokenize.pop(),n.tokenize[n.tokenize.length-1](t,n)}else"{"==t.peek()&&e++;return u(t,n)}return t.isBase=!0,t}function p(e,t){var n=e.match(/^(\.|[\w\$_]+)/);return n?"."==n[0]?null:"variable":(t.tokenize.pop(),t.tokenize[t.tokenize.length-1](e,t))}function k(e,t){for(var n,r=!1;n=e.next();){if("/"==n&&r){t.tokenize.pop();break}r="*"==n}return"comment"}function m(e,t){return!e||"operator"==e||"->"==e||/[\.\[\{\(,;:]/.test(e)||"newstatement"==e||"keyword"==e||"proplabel"==e||"standalone"==e&&!t}function h(e,t,n,r,i){this.indented=e,this.column=t,this.type=n,this.align=r,this.prev=i}function d(e,t,n){return e.context=new h(e.indented,t,n,null,e.context)}function y(e){var t=e.context.type;return")"!=t&&"]"!=t&&"}"!=t||(e.indented=e.context.indented),e.context=e.context.prev}u.isBase=!0;const v={name:"groovy",startState:function(e){return{tokenize:[u],context:new h(-e,0,"top",!1),indented:0,startOfLine:!0,lastToken:null}},token:function(e,t){var n=t.context;if(e.sol()&&(null==n.align&&(n.align=!1),t.indented=e.indentation(),t.startOfLine=!0,"statement"!=n.type||m(t.lastToken,!0)||(y(t),n=t.context)),e.eatSpace())return null;i=null;var r=t.tokenize[t.tokenize.length-1](e,t);if("comment"==r)return r;if(null==n.align&&(n.align=!0),";"!=i&&":"!=i||"statement"!=n.type)if("->"==i&&"statement"==n.type&&"}"==n.prev.type)y(t),t.context.align=!1;else if("{"==i)d(t,e.column(),"}");else if("["==i)d(t,e.column(),"]");else if("("==i)d(t,e.column(),")");else if("}"==i){for(;"statement"==n.type;)n=y(t);for("}"==n.type&&(n=y(t));"statement"==n.type;)n=y(t)}else i==n.type?y(t):("}"==n.type||"top"==n.type||"statement"==n.type&&"newstatement"==i)&&d(t,e.column(),"statement");else y(t);return t.startOfLine=!1,t.lastToken=i||r,r},indent:function(e,t,n){if(!e.tokenize[e.tokenize.length-1].isBase)return null;var r=t&&t.charAt(0),i=e.context;"statement"!=i.type||m(e.lastToken,!0)||(i=i.prev);var a=r==i.type;return"statement"==i.type?i.indented+("{"==r?0:n.unit):i.align?i.column+(a?0:1):i.indented+(a?0:n.unit)},languageData:{indentOnInput:/^\s*[{}]$/,commentTokens:{line:"//",block:{open:"/*",close:"*/"}},closeBrackets:{brackets:["(","[","{","'",'"',"'''",'"""']}}}}}]);
+//# sourceMappingURL=22.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/22.index.js.map b/book/_build/html/_static/22.index.js.map
new file mode 100644
index 0000000..71abac8
--- /dev/null
+++ b/book/_build/html/_static/22.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"22.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/groovy.js"],"sourcesContent":["function words(str) {\n var obj = {}, words = str.split(\" \");\n for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n return obj;\n}\nvar keywords = words(\n \"abstract as assert boolean break byte case catch char class const continue def default \" +\n \"do double else enum extends final finally float for goto if implements import in \" +\n \"instanceof int interface long native new package private protected public return \" +\n \"short static strictfp super switch synchronized threadsafe throw throws trait transient \" +\n \"try void volatile while\");\nvar blockKeywords = words(\"catch class def do else enum finally for if interface switch trait try while\");\nvar standaloneKeywords = words(\"return break continue\");\nvar atoms = words(\"null true false this\");\n\nvar curPunc;\nfunction tokenBase(stream, state) {\n var ch = stream.next();\n if (ch == '\"' || ch == \"'\") {\n return startString(ch, stream, state);\n }\n if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n curPunc = ch;\n return null;\n }\n if (/\\d/.test(ch)) {\n stream.eatWhile(/[\\w\\.]/);\n if (stream.eat(/eE/)) { stream.eat(/\\+\\-/); stream.eatWhile(/\\d/); }\n return \"number\";\n }\n if (ch == \"/\") {\n if (stream.eat(\"*\")) {\n state.tokenize.push(tokenComment);\n return tokenComment(stream, state);\n }\n if (stream.eat(\"/\")) {\n stream.skipToEnd();\n return \"comment\";\n }\n if (expectExpression(state.lastToken, false)) {\n return startString(ch, stream, state);\n }\n }\n if (ch == \"-\" && stream.eat(\">\")) {\n curPunc = \"->\";\n return null;\n }\n if (/[+\\-*&%=<>!?|\\/~]/.test(ch)) {\n stream.eatWhile(/[+\\-*&%=<>|~]/);\n return \"operator\";\n }\n stream.eatWhile(/[\\w\\$_]/);\n if (ch == \"@\") { stream.eatWhile(/[\\w\\$_\\.]/); return \"meta\"; }\n if (state.lastToken == \".\") return \"property\";\n if (stream.eat(\":\")) { curPunc = \"proplabel\"; return \"property\"; }\n var cur = stream.current();\n if (atoms.propertyIsEnumerable(cur)) { return \"atom\"; }\n if (keywords.propertyIsEnumerable(cur)) {\n if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n else if (standaloneKeywords.propertyIsEnumerable(cur)) curPunc = \"standalone\";\n return \"keyword\";\n }\n return \"variable\";\n}\ntokenBase.isBase = true;\n\nfunction startString(quote, stream, state) {\n var tripleQuoted = false;\n if (quote != \"/\" && stream.eat(quote)) {\n if (stream.eat(quote)) tripleQuoted = true;\n else return \"string\";\n }\n function t(stream, state) {\n var escaped = false, next, end = !tripleQuoted;\n while ((next = stream.next()) != null) {\n if (next == quote && !escaped) {\n if (!tripleQuoted) { break; }\n if (stream.match(quote + quote)) { end = true; break; }\n }\n if (quote == '\"' && next == \"$\" && !escaped) {\n if (stream.eat(\"{\")) {\n state.tokenize.push(tokenBaseUntilBrace());\n return \"string\";\n } else if (stream.match(/^\\w/, false)) {\n state.tokenize.push(tokenVariableDeref);\n return \"string\";\n }\n }\n escaped = !escaped && next == \"\\\\\";\n }\n if (end) state.tokenize.pop();\n return \"string\";\n }\n state.tokenize.push(t);\n return t(stream, state);\n}\n\nfunction tokenBaseUntilBrace() {\n var depth = 1;\n function t(stream, state) {\n if (stream.peek() == \"}\") {\n depth--;\n if (depth == 0) {\n state.tokenize.pop();\n return state.tokenize[state.tokenize.length-1](stream, state);\n }\n } else if (stream.peek() == \"{\") {\n depth++;\n }\n return tokenBase(stream, state);\n }\n t.isBase = true;\n return t;\n}\n\nfunction tokenVariableDeref(stream, state) {\n var next = stream.match(/^(\\.|[\\w\\$_]+)/)\n if (!next) {\n state.tokenize.pop()\n return state.tokenize[state.tokenize.length-1](stream, state)\n }\n return next[0] == \".\" ? null : \"variable\"\n}\n\nfunction tokenComment(stream, state) {\n var maybeEnd = false, ch;\n while (ch = stream.next()) {\n if (ch == \"/\" && maybeEnd) {\n state.tokenize.pop();\n break;\n }\n maybeEnd = (ch == \"*\");\n }\n return \"comment\";\n}\n\nfunction expectExpression(last, newline) {\n return !last || last == \"operator\" || last == \"->\" || /[\\.\\[\\{\\(,;:]/.test(last) ||\n last == \"newstatement\" || last == \"keyword\" || last == \"proplabel\" ||\n (last == \"standalone\" && !newline);\n}\n\nfunction Context(indented, column, type, align, prev) {\n this.indented = indented;\n this.column = column;\n this.type = type;\n this.align = align;\n this.prev = prev;\n}\nfunction pushContext(state, col, type) {\n return state.context = new Context(state.indented, col, type, null, state.context);\n}\nfunction popContext(state) {\n var t = state.context.type;\n if (t == \")\" || t == \"]\" || t == \"}\")\n state.indented = state.context.indented;\n return state.context = state.context.prev;\n}\n\n// Interface\n\nexport const groovy = {\n name: \"groovy\",\n startState: function(indentUnit) {\n return {\n tokenize: [tokenBase],\n context: new Context(-indentUnit, 0, \"top\", false),\n indented: 0,\n startOfLine: true,\n lastToken: null\n };\n },\n\n token: function(stream, state) {\n var ctx = state.context;\n if (stream.sol()) {\n if (ctx.align == null) ctx.align = false;\n state.indented = stream.indentation();\n state.startOfLine = true;\n // Automatic semicolon insertion\n if (ctx.type == \"statement\" && !expectExpression(state.lastToken, true)) {\n popContext(state); ctx = state.context;\n }\n }\n if (stream.eatSpace()) return null;\n curPunc = null;\n var style = state.tokenize[state.tokenize.length-1](stream, state);\n if (style == \"comment\") return style;\n if (ctx.align == null) ctx.align = true;\n\n if ((curPunc == \";\" || curPunc == \":\") && ctx.type == \"statement\") popContext(state);\n // Handle indentation for {x -> \\n ... }\n else if (curPunc == \"->\" && ctx.type == \"statement\" && ctx.prev.type == \"}\") {\n popContext(state);\n state.context.align = false;\n }\n else if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n else if (curPunc == \"}\") {\n while (ctx.type == \"statement\") ctx = popContext(state);\n if (ctx.type == \"}\") ctx = popContext(state);\n while (ctx.type == \"statement\") ctx = popContext(state);\n }\n else if (curPunc == ctx.type) popContext(state);\n else if (ctx.type == \"}\" || ctx.type == \"top\" || (ctx.type == \"statement\" && curPunc == \"newstatement\"))\n pushContext(state, stream.column(), \"statement\");\n state.startOfLine = false;\n state.lastToken = curPunc || style;\n return style;\n },\n\n indent: function(state, textAfter, cx) {\n if (!state.tokenize[state.tokenize.length-1].isBase) return null;\n var firstChar = textAfter && textAfter.charAt(0), ctx = state.context;\n if (ctx.type == \"statement\" && !expectExpression(state.lastToken, true)) ctx = ctx.prev;\n var closing = firstChar == ctx.type;\n if (ctx.type == \"statement\") return ctx.indented + (firstChar == \"{\" ? 0 : cx.unit);\n else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n else return ctx.indented + (closing ? 0 : cx.unit);\n },\n\n languageData: {\n indentOnInput: /^\\s*[{}]$/,\n commentTokens: {line: \"//\", block: {open: \"/*\", close: \"*/\"}},\n closeBrackets: {brackets: [\"(\", \"[\", \"{\", \"'\", '\"', \"'''\", '\"\"\"']}\n }\n};\n"],"names":["words","str","obj","split","i","length","curPunc","keywords","blockKeywords","standaloneKeywords","atoms","tokenBase","stream","state","ch","next","startString","test","eatWhile","eat","tokenize","push","tokenComment","skipToEnd","expectExpression","lastToken","cur","current","propertyIsEnumerable","quote","tripleQuoted","t","escaped","end","match","tokenBaseUntilBrace","tokenVariableDeref","pop","depth","peek","isBase","maybeEnd","last","newline","Context","indented","column","type","align","prev","this","pushContext","col","context","popContext","groovy","name","startState","indentUnit","startOfLine","token","ctx","sol","indentation","eatSpace","style","indent","textAfter","cx","firstChar","charAt","closing","unit","languageData","indentOnInput","commentTokens","line","block","open","close","closeBrackets","brackets"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/2210.index.js b/book/_build/html/_static/2210.index.js
new file mode 100644
index 0000000..fe72f7e
--- /dev/null
+++ b/book/_build/html/_static/2210.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[2210],{52210:(e,t,r)=>{r.r(t),r.d(t,{pascal:()=>u});var n=function(e){for(var t={},r="absolute and array asm begin case const constructor destructor div do downto else end file for function goto if implementation in inherited inline interface label mod nil not object of operator or packed procedure program record reintroduce repeat self set shl shr string then to type unit until uses var while with xor as class dispinterface except exports finalization finally initialization inline is library on out packed property raise resourcestring threadvar try absolute abstract alias assembler bitpacked break cdecl continue cppdecl cvar default deprecated dynamic enumerator experimental export external far far16 forward generic helper implements index interrupt iocheck local message name near nodefault noreturn nostackframe oldfpccall otherwise overload override pascal platform private protected public published read register reintroduce result safecall saveregisters softfloat specialize static stdcall stored strict unaligned unimplemented varargs virtual write".split(" "),n=0;n!?|\/]/;function o(e,t){var r,o=e.next();if("#"==o&&t.startOfLine)return e.skipToEnd(),"meta";if('"'==o||"'"==o)return t.tokenize=(r=o,function(e,t){for(var n,a=!1,i=!1;null!=(n=e.next());){if(n==r&&!a){i=!0;break}a=!a&&"\\"==n}return!i&&a||(t.tokenize=null),"string"}),t.tokenize(e,t);if("("==o&&e.eat("*"))return t.tokenize=l,l(e,t);if("{"==o)return t.tokenize=s,s(e,t);if(/[\[\]\(\),;\:\.]/.test(o))return null;if(/\d/.test(o))return e.eatWhile(/[\w\.]/),"number";if("/"==o&&e.eat("/"))return e.skipToEnd(),"comment";if(i.test(o))return e.eatWhile(i),"operator";e.eatWhile(/[\w\$_]/);var u=e.current();return n.propertyIsEnumerable(u)?"keyword":a.propertyIsEnumerable(u)?"atom":"variable"}function l(e,t){for(var r,n=!1;r=e.next();){if(")"==r&&n){t.tokenize=null;break}n="*"==r}return"comment"}function s(e,t){for(var r;r=e.next();)if("}"==r){t.tokenize=null;break}return"comment"}const u={name:"pascal",startState:function(){return{tokenize:null}},token:function(e,t){return e.eatSpace()?null:(t.tokenize||o)(e,t)},languageData:{indentOnInput:/^\s*[{}]$/,commentTokens:{block:{open:"(*",close:"*)"}}}}}}]);
+//# sourceMappingURL=2210.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/2210.index.js.map b/book/_build/html/_static/2210.index.js.map
new file mode 100644
index 0000000..15521f6
--- /dev/null
+++ b/book/_build/html/_static/2210.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"2210.index.js","mappings":"4HAKA,IAAIA,EALJ,SAAeC,GAEb,IADA,IAAIC,EAAM,CAAC,EAAGC,EAKd,u9BAL0BC,MAAM,KACvBC,EAAI,EAAGA,EAAIF,EAAMG,SAAUD,EAAGH,EAAIC,EAAME,KAAM,EACvD,OAAOH,CACT,CACeC,GAeXI,EAAQ,CAAC,MAAQ,GAEjBC,EAAiB,mBAErB,SAASC,EAAUC,EAAQC,GACzB,IAyCmBC,EAzCfC,EAAKH,EAAOI,OAChB,GAAU,KAAND,GAAaF,EAAMI,YAErB,OADAL,EAAOM,YACA,OAET,GAAU,KAANH,GAAmB,KAANA,EAEf,OADAF,EAAMM,UAmCWL,EAnCYC,EAoCxB,SAASH,EAAQC,GAEtB,IADA,IAAqBG,EAAjBI,GAAU,EAAaC,GAAM,EACA,OAAzBL,EAAOJ,EAAOI,SAAiB,CACrC,GAAIA,GAAQF,IAAUM,EAAS,CAACC,GAAM,EAAM,KAAM,CAClDD,GAAWA,GAAmB,MAARJ,CACxB,CAEA,OADIK,GAAQD,IAASP,EAAMM,SAAW,MAC/B,QACT,GA3CSN,EAAMM,SAASP,EAAQC,GAEhC,GAAU,KAANE,GAAaH,EAAOU,IAAI,KAE1B,OADAT,EAAMM,SAAWI,EACVA,EAAaX,EAAQC,GAE9B,GAAU,KAANE,EAEF,OADAF,EAAMM,SAAWK,EACVA,EAAmBZ,EAAQC,GAEpC,GAAI,mBAAmBY,KAAKV,GAC1B,OAAO,KAET,GAAI,KAAKU,KAAKV,GAEZ,OADAH,EAAOc,SAAS,UACT,SAET,GAAU,KAANX,GACEH,EAAOU,IAAI,KAEb,OADAV,EAAOM,YACA,UAGX,GAAIR,EAAee,KAAKV,GAEtB,OADAH,EAAOc,SAAShB,GACT,WAETE,EAAOc,SAAS,WAChB,IAAIC,EAAMf,EAAOgB,UACjB,OAAI1B,EAAS2B,qBAAqBF,GAAa,UAC3ClB,EAAMoB,qBAAqBF,GAAa,OACrC,UACT,CAcA,SAASJ,EAAaX,EAAQC,GAE5B,IADA,IAAsBE,EAAlBe,GAAW,EACRf,EAAKH,EAAOI,QAAQ,CACzB,GAAU,KAAND,GAAae,EAAU,CACzBjB,EAAMM,SAAW,KACjB,KACF,CACAW,EAAkB,KAANf,CACd,CACA,MAAO,SACT,CAEA,SAASS,EAAmBZ,EAAQC,GAElC,IADA,IAAIE,EACGA,EAAKH,EAAOI,QACjB,GAAU,KAAND,EAAW,CACbF,EAAMM,SAAW,KACjB,KACF,CAEF,MAAO,SACT,CAIO,MAAMY,EAAS,CACpBC,KAAM,SAENC,WAAY,WACV,MAAO,CAACd,SAAU,KACpB,EAEAe,MAAO,SAAStB,EAAQC,GACtB,OAAID,EAAOuB,WAAmB,MACjBtB,EAAMM,UAAYR,GAAWC,EAAQC,EAGpD,EAEAuB,aAAc,CACZC,cAAe,YACfC,cAAe,CAACC,MAAO,CAACC,KAAM,KAAMC,MAAO,Q","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/pascal.js"],"sourcesContent":["function words(str) {\n var obj = {}, words = str.split(\" \");\n for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n return obj;\n}\nvar keywords = words(\n \"absolute and array asm begin case const constructor destructor div do \" +\n \"downto else end file for function goto if implementation in inherited \" +\n \"inline interface label mod nil not object of operator or packed procedure \" +\n \"program record reintroduce repeat self set shl shr string then to type \" +\n \"unit until uses var while with xor as class dispinterface except exports \" +\n \"finalization finally initialization inline is library on out packed \" +\n \"property raise resourcestring threadvar try absolute abstract alias \" +\n \"assembler bitpacked break cdecl continue cppdecl cvar default deprecated \" +\n \"dynamic enumerator experimental export external far far16 forward generic \" +\n \"helper implements index interrupt iocheck local message name near \" +\n \"nodefault noreturn nostackframe oldfpccall otherwise overload override \" +\n \"pascal platform private protected public published read register \" +\n \"reintroduce result safecall saveregisters softfloat specialize static \" +\n \"stdcall stored strict unaligned unimplemented varargs virtual write\");\nvar atoms = {\"null\": true};\n\nvar isOperatorChar = /[+\\-*&%=<>!?|\\/]/;\n\nfunction tokenBase(stream, state) {\n var ch = stream.next();\n if (ch == \"#\" && state.startOfLine) {\n stream.skipToEnd();\n return \"meta\";\n }\n if (ch == '\"' || ch == \"'\") {\n state.tokenize = tokenString(ch);\n return state.tokenize(stream, state);\n }\n if (ch == \"(\" && stream.eat(\"*\")) {\n state.tokenize = tokenComment;\n return tokenComment(stream, state);\n }\n if (ch == \"{\") {\n state.tokenize = tokenCommentBraces;\n return tokenCommentBraces(stream, state);\n }\n if (/[\\[\\]\\(\\),;\\:\\.]/.test(ch)) {\n return null;\n }\n if (/\\d/.test(ch)) {\n stream.eatWhile(/[\\w\\.]/);\n return \"number\";\n }\n if (ch == \"/\") {\n if (stream.eat(\"/\")) {\n stream.skipToEnd();\n return \"comment\";\n }\n }\n if (isOperatorChar.test(ch)) {\n stream.eatWhile(isOperatorChar);\n return \"operator\";\n }\n stream.eatWhile(/[\\w\\$_]/);\n var cur = stream.current();\n if (keywords.propertyIsEnumerable(cur)) return \"keyword\";\n if (atoms.propertyIsEnumerable(cur)) return \"atom\";\n return \"variable\";\n}\n\nfunction tokenString(quote) {\n return function(stream, state) {\n var escaped = false, next, end = false;\n while ((next = stream.next()) != null) {\n if (next == quote && !escaped) {end = true; break;}\n escaped = !escaped && next == \"\\\\\";\n }\n if (end || !escaped) state.tokenize = null;\n return \"string\";\n };\n}\n\nfunction tokenComment(stream, state) {\n var maybeEnd = false, ch;\n while (ch = stream.next()) {\n if (ch == \")\" && maybeEnd) {\n state.tokenize = null;\n break;\n }\n maybeEnd = (ch == \"*\");\n }\n return \"comment\";\n}\n\nfunction tokenCommentBraces(stream, state) {\n var ch;\n while (ch = stream.next()) {\n if (ch == \"}\") {\n state.tokenize = null;\n break;\n }\n }\n return \"comment\";\n}\n\n// Interface\n\nexport const pascal = {\n name: \"pascal\",\n\n startState: function() {\n return {tokenize: null};\n },\n\n token: function(stream, state) {\n if (stream.eatSpace()) return null;\n var style = (state.tokenize || tokenBase)(stream, state);\n if (style == \"comment\" || style == \"meta\") return style;\n return style;\n },\n\n languageData: {\n indentOnInput: /^\\s*[{}]$/,\n commentTokens: {block: {open: \"(*\", close: \"*)\"}}\n }\n};\n"],"names":["keywords","str","obj","words","split","i","length","atoms","isOperatorChar","tokenBase","stream","state","quote","ch","next","startOfLine","skipToEnd","tokenize","escaped","end","eat","tokenComment","tokenCommentBraces","test","eatWhile","cur","current","propertyIsEnumerable","maybeEnd","pascal","name","startState","token","eatSpace","languageData","indentOnInput","commentTokens","block","open","close"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/2377.index.js b/book/_build/html/_static/2377.index.js
new file mode 100644
index 0000000..074b741
--- /dev/null
+++ b/book/_build/html/_static/2377.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[2377],{22377:(O,r,a)=>{a.r(r),a.d(r,{globalCompletion:()=>g,localCompletionSource:()=>h,python:()=>z,pythonLanguage:()=>U});var Q=a(51392),i=a(86253);const x=10,S=13,o=123,e=92,T=new Set([27,51,52,270,67,133,58,59,251,64,65,74,62,63,154,155,158,115]);function t(O){return O==x||O==S}const s=new Q.Jq(((O,r)=>{let a;if(O.next<0)O.acceptToken(206);else if(r.context.depth<0)t(O.next)&&O.acceptToken(205,1);else if(((a=O.peek(-1))<0||t(a))&&r.canShift(204)){let r=0;for(;32==O.next||9==O.next;)O.advance(),r++;O.next!=x&&O.next!=S&&35!=O.next||O.acceptToken(204,-r)}else t(O.next)&&O.acceptToken(203,1)}),{contextual:!0}),n=new Q.Jq(((O,r)=>{let a=r.context.depth;if(a<0)return;let Q=O.peek(-1);if(Q==x||Q==S){let r=0,Q=0;for(;;){if(32==O.next)r++;else{if(9!=O.next)break;r+=8-r%8}O.advance(),Q++}r!=a&&O.next!=x&&O.next!=S&&35!=O.next&&(rO.depth<0&&T.has(r)?O.parent:O,shift:(O,r,a,Q)=>201==r?new p(O,function(O){let r=0;for(let a=0;aO.hash}),l=new Q.Jq((O=>{for(let r=0;r<5;r++){if(O.next!="print".charCodeAt(r))return;O.advance()}if(!/\w/.test(String.fromCharCode(O.next)))for(let r=0;;r++){let a=O.peek(r);if(32!=a&&9!=a)return void(40!=a&&46!=a&&a!=x&&a!=S&&35!=a&&O.acceptToken(1))}}));function $(O,r,a,i,x){return new Q.Jq((Q=>{let S=Q.pos;for(;!(Q.next<0);)if(Q.next==o){if(Q.peek(1)!=o){if(Q.pos==S)return void Q.acceptToken(i,1);break}Q.advance(2)}else if(Q.next==e)Q.advance(),Q.next>=0&&Q.advance();else{if(Q.next==O&&(1==r||Q.peek(1)==O&&Q.peek(2)==O)){if(Q.pos==S)return void Q.acceptToken(x,r);break}Q.advance()}Q.pos>S&&Q.acceptToken(a)}))}const X=$(39,1,207,2,208),w=$(34,1,209,3,210),Y=$(39,3,211,4,212),c=$(34,3,213,5,214),m=(0,i.Gv)({'async "*" "**" FormatConversion FormatSpec':i.pJ.modifier,"for while if elif else try except finally return raise break continue with pass assert await yield match case":i.pJ.controlKeyword,"in not and or is del":i.pJ.operatorKeyword,"from def class global nonlocal lambda":i.pJ.definitionKeyword,import:i.pJ.moduleKeyword,"with as print":i.pJ.keyword,Boolean:i.pJ.bool,None:i.pJ.null,VariableName:i.pJ.variableName,"CallExpression/VariableName":i.pJ.function(i.pJ.variableName),"FunctionDefinition/VariableName":i.pJ.function(i.pJ.definition(i.pJ.variableName)),"ClassDefinition/VariableName":i.pJ.definition(i.pJ.className),PropertyName:i.pJ.propertyName,"CallExpression/MemberExpression/PropertyName":i.pJ.function(i.pJ.propertyName),Comment:i.pJ.lineComment,Number:i.pJ.number,String:i.pJ.string,FormatString:i.pJ.special(i.pJ.string),UpdateOp:i.pJ.updateOperator,"ArithOp!":i.pJ.arithmeticOperator,BitOp:i.pJ.bitwiseOperator,CompareOp:i.pJ.compareOperator,AssignOp:i.pJ.definitionOperator,Ellipsis:i.pJ.punctuation,At:i.pJ.meta,"( )":i.pJ.paren,"[ ]":i.pJ.squareBracket,"{ }":i.pJ.brace,".":i.pJ.derefOperator,", ;":i.pJ.separator}),d={__proto__:null,await:48,or:58,and:60,in:64,not:66,is:68,if:74,else:76,lambda:80,yield:98,from:100,async:106,for:108,None:168,True:170,False:170,del:184,pass:188,break:192,continue:196,return:200,raise:208,import:212,as:214,global:218,nonlocal:220,assert:224,type:229,elif:242,while:246,try:252,except:254,finally:256,with:260,def:264,class:274,match:285,case:291},f=Q.WQ.deserialize({version:14,states:"#&jO`Q#yOOP$bOSOOO%kQ&nO'#HcOOQS'#Cq'#CqOOQS'#Cr'#CrO'ZQ#xO'#CpO(|Q&nO'#HbOOQS'#Hc'#HcOOQS'#DW'#DWOOQS'#Hb'#HbO)jQ#xO'#DaO)}Q#xO'#DhO*_Q#xO'#DlOOQS'#Dw'#DwO*rO,UO'#DwO*zO7[O'#DwO+SOWO'#DxO+_O`O'#DxO+jOpO'#DxO+uO!bO'#DxO-wQ&nO'#HSOOQS'#HS'#HSO'ZQ#xO'#HRO/ZQ&nO'#HROOQS'#Ee'#EeO/rQ#xO'#EfOOQS'#HQ'#HQO/|Q#xO'#HPOOQV'#HP'#HPO0XQ#xO'#F]OOQS'#Ge'#GeO0^Q#xO'#F[OOQV'#IY'#IYOOQV'#HO'#HOOOQV'#Ft'#FtQ`Q#yOOO'ZQ#xO'#CsO0lQ#xO'#DPO0sQ#xO'#DTO1RQ#xO'#HgO1cQ&nO'#EYO'ZQ#xO'#EZOOQS'#E]'#E]OOQS'#E_'#E_OOQS'#Ea'#EaO1wQ#xO'#EcO2_Q#xO'#EgO0XQ#xO'#EiO2rQ&nO'#EiO0XQ#xO'#ElO/rQ#xO'#EoO0XQ#xO'#EqO/rQ#xO'#EwO/rQ#xO'#EzO2}Q#xO'#E|O3UQ#xO'#FRO3aQ#xO'#E}O/rQ#xO'#FRO0XQ#xO'#FTO0XQ#xO'#FYO3fQ#xO'#F_P3mO#xO'#G}POOO)CBq)CBqOOQS'#Cg'#CgOOQS'#Ch'#ChOOQS'#Ci'#CiOOQS'#Cj'#CjOOQS'#Ck'#CkOOQS'#Cl'#ClOOQS'#Cn'#CnO'ZQ#xO,59QO'ZQ#xO,59QO'ZQ#xO,59QO'ZQ#xO,59QO'ZQ#xO,59QO'ZQ#xO,59QO3xQ#xO'#DqOOQS,5:[,5:[O4]Q#xO'#HqOOQS,5:_,5:_O4jQMlO,5:_O4oQ&nO,59[O0lQ#xO,59dO0lQ#xO,59dO0lQ#xO,59dO7_Q#xO,59dO7dQ#xO,59dO7kQ#xO,59lO7rQ#xO'#HbO8xQ#xO'#HaOOQS'#Ha'#HaOOQS'#D^'#D^O9aQ#xO,59cO'ZQ#xO,59cO9oQ#xO,59cOOQS,59{,59{O9tQ#xO,5:TO'ZQ#xO,5:TOOQS,5:S,5:SO:SQ#xO,5:SO:XQ#xO,5:ZO'ZQ#xO,5:ZO'ZQ#xO,5:XOOQS,5:W,5:WO:jQ#xO,5:WO:oQ#xO,5:YOOOO'#F|'#F|O:tO,UO,5:cOOQS,5:c,5:cOOOO'#F}'#F}O:|O7[O,5:cO;UQ#xO'#DyOOOW'#GO'#GOO;fOWO,5:dOOQS,5:d,5:dO;UQ#xO'#D}OOO`'#GR'#GRO;qO`O,5:dO;UQ#xO'#EOOOOp'#GS'#GSO;|OpO,5:dO;UQ#xO'#EPOOO!b'#GT'#GTOROOQS,5>R,5>RO/rQ#xO'#EUOOQS'#EV'#EVOGZQ#xO'#GWOGkQ#xO,59OOGkQ#xO,59OO)pQ#xO,5:rOGyQ&nO'#HjOOQS,5:u,5:uOOQS,5:},5:}OH^Q#xO,5;ROHoQ#xO,5;TOOQS'#GZ'#GZOH}Q&nO,5;TOI]Q#xO,5;TOIbQ#xO'#IWOOQS,5;W,5;WOIpQ#xO'#ISOOQS,5;Z,5;ZOJRQ#xO,5;]O3aQ#xO,5;cO3aQ#xO,5;fOJZQ&nO'#IZO'ZQ#xO'#IZOJeQ#xO,5;hO2}Q#xO,5;hO/rQ#xO,5;mO0XQ#xO,5;oOJjQ#yO'#ExOKvQ#{O,5;iO! [Q#xO'#I[O3aQ#xO,5;mO! gQ#xO,5;oO! oQ#xO,5;tO! zQ&nO,5;yO'ZQ#xO,5;yPOOO,5=i,5=iP!!ROSO,5=iP!!WO#xO,5=iO!${Q&nO1G.lO!%SQ&nO1G.lO!'sQ&nO1G.lO!'}Q&nO1G.lO!*hQ&nO1G.lO!*{Q&nO1G.lO!+`Q#xO'#HpO!+nQ&nO'#HSO/rQ#xO'#HpO!+xQ#xO'#HoOOQS,5:],5:]O!,QQ#xO,5:]O!,VQ#xO'#HrO!,bQ#xO'#HrO!,uQ#xO,5>]OOQS'#Du'#DuOOQS1G/y1G/yOOQS1G/O1G/OO!-uQ&nO1G/OO!-|Q&nO1G/OO0lQ#xO1G/OO!.iQ#xO1G/WOOQS'#D]'#D]O/rQ#xO,59vOOQS1G.}1G.}O!.pQ#xO1G/gO!/QQ#xO1G/gO!/YQ#xO1G/hO'ZQ#xO'#HiO!/_Q#xO'#HiO!/dQ&nO1G.}O!/tQ#xO,59kO!0zQ#xO,5>XO!1[Q#xO,5>XO!1dQ#xO1G/oO!1iQ&nO1G/oOOQS1G/n1G/nO!1yQ#xO,5>SO!2pQ#xO,5>SO/rQ#xO1G/sO!3_Q#xO1G/uO!3dQ&nO1G/uO!3tQ&nO1G/sOOQS1G/r1G/rOOQS1G/t1G/tOOOO-E9z-E9zOOQS1G/}1G/}OOOO-E9{-E9{O!4UQ#xO'#H|O/rQ#xO'#H|O!4dQ#xO,5:eOOOW-E9|-E9|OOQS1G0O1G0OO!4oQ#xO,5:iOOO`-E:P-E:PO!4zQ#xO,5:jOOOp-E:Q-E:QO!5VQ#xO,5:kOOO!b-E:R-E:ROOQS-E:S-E:SO!5bQ!LUO1G3XO!6RQ&nO1G3XO'ZQ#xO,5oOOQS1G1c1G1cO!7RQ#xO1G1cOOQS'#DX'#DXO/rQ#xO,5>OOOQS,5>O,5>OO!7WQ#xO'#FuO!7cQ#xO,59qO!7kQ#xO1G/ZO!7uQ&nO,5>SOOQS1G3m1G3mOOQS,5:p,5:pO!8fQ#xO'#HROOQS,5UO!9gQ#xO,5>UO/rQ#xO1G0mO/rQ#xO1G0mO0XQ#xO1G0oOOQS-E:X-E:XO!9xQ#xO1G0oO!:TQ#xO1G0oO!:YQ#xO,5>rO!:hQ#xO,5>rO!:vQ#xO,5>nO!;^Q#xO,5>nO!;oQ#xO'#EsO/rQ#xO1G0wO!;zQ#xO1G0wO!uO!BzQ#xO,5>uO!CSQ&nO,5>uO/rQ#xO1G1SO!C^Q#xO1G1SO3aQ#xO1G1XO! gQ#xO1G1ZOOQV,5;d,5;dO!CcQ#zO,5;dO!ChQ#{O1G1TO!F|Q#xO'#GbO3aQ#xO1G1TO3aQ#xO1G1TO!G^Q#xO,5>vO!GkQ#xO,5>vO0XQ#xO,5>vOOQV1G1X1G1XO!GsQ#xO'#FVO!HUQMlO1G1ZO!H^Q#xO1G1ZOOQV1G1`1G1`O3aQ#xO1G1`O!HcQ#xO1G1`O!HkQ#xO'#FaOOQV1G1e1G1eO! zQ&nO1G1ePOOO1G3T1G3TP!HpOSO1G3TOOQS,5>[,5>[OOQS'#Dr'#DrO/rQ#xO,5>[O!HuQ#xO,5>ZO!IYQ#xO,5>ZOOQS1G/w1G/wO!IbQ#xO,5>^O!IrQ#xO,5>^O!IzQ#xO,5>^O!J_Q#xO,5>^O!JoQ#xO,5>^OOQS1G3w1G3wOOQS7+$j7+$jO!7kQ#xO7+$rO!LbQ#xO1G/OO!LiQ#xO1G/OOOQS1G/b1G/bOOQS,5TO'ZQ#xO,5>TOOQS7+$i7+$iO!MVQ#xO7+%RO!M_Q#xO7+%SO!MdQ#xO1G3sOOQS7+%Z7+%ZO!MtQ#xO1G3sO!M|Q#xO7+%ZOOQS,5hO##PQ#xO,5>hO##PQ#xO,5>hO##_O$ISO'#D{O##jO#tO'#H}OOOW1G0P1G0PO##oQ#xO1G0POOO`1G0T1G0TO##wQ#xO1G0TOOOp1G0U1G0UO#$PQ#xO1G0UOOO!b1G0V1G0VO#$XQ#xO1G0VO#$aQ!LUO7+(sO#%QQ&nO1G2]P#%kQ#xO'#GVOOQS,5i,5>iOOOW7+%k7+%kOOO`7+%o7+%oOOOp7+%p7+%pOOO!b7+%q7+%qO#:`Q#xO1G3XO#:yQ#xO1G3XP'ZQ#xO'#FxO/rQ#xO<qO#;mQ#xO,5>qO0XQ#xO,5>qO#pOOQS<sO#sOOQS1G0y1G0yOOQS<xO#DpQ#xO,5>xOOQS,5>x,5>xO#D{Q#xO,5>wO#E^Q#xO,5>wOOQS1G1]1G1]OOQS,5;s,5;sOOQV<XAN>XO#HmQ#xO<eAN>eO/rQ#xO1G2PO#H}Q&nO1G2PP#IXQ#xO'#FyOOQS1G2V1G2VP#IfQ#xO'#GPO#IsQ#xO7+)nO#JZQ#xO,5:hOOOO-E:O-E:OO#JfQ#xO7+(sOOQSAN?_AN?_O#KPQ#xO,5VOOQSANBaANBaOOOO7+%n7+%nOOQS7+'|7+'|O$+jQ#xO<zO$.`Q#xO,5>zO0XQ#xO,5|O$!pQ#xO,5>|OOQS1G1s1G1sO$2WQ&nO,5<_OOQU7+'S7+'SO$$mQ#xO1G/kO$!pQ#xO,5<]O$2_Q#xO,5>}O$2fQ#xO,5>}OOQS1G1v1G1vOOQS7+'V7+'VP$!pQ#xO'#GkO$2nQ#xO1G4hO$2xQ#xO1G4hO$3QQ#xO1G4hOOQS7+%V7+%VO$3`Q#xO1G1wO$3nQ&nO'#FdO$3uQ#xO,5=UOOQS,5=U,5=UO$4TQ#xO1G4iOOQS-E:h-E:hO$!pQ#xO,5=TO$4[Q#xO,5=TO$4aQ#xO7+*SOOQS-E:g-E:gO$4kQ#xO7+*SO$!pQ#xO,5<^P$!pQ#xO'#GjO$4sQ#xO1G2oO$!pQ#xO1G2oP$5RQ#xO'#GiO$5YQ#xO<fPP>i?Z?^PP'a'aPP?vPP'a'aPP'a'a'a'a'a?z@t'aP@wP@}EXHxPH|IYI^IbIf'aPPPIjIs'XP'X'XP'XP'XP'XP'XP'X'X'XP'XPP'XPP'XP'XPIyJVJ_PJfJlPJfPJfJfPPPJfPLzPMTM_MeLzPJfMnPJfPMuM{PNPNe! S! mNPNP! s!!QNPNPNPNP!!f!!l!!o!!t!!w!#R!#X!#e!#w!#}!$X!$_!${!%R!%X!%_!%i!%o!%u!%{!&R!&X!&k!&u!&{!'R!'X!'c!'i!'o!'u!'{!(V!(]!(g!(m!(v!(|!)]!)e!)o!)vPPPPPPPPPPPPPPPPP!)|!*P!*V!*`!*j!*uPPPPPPPPPPPP!/l!1Q!5T!8hPP!8p!9S!9]!:U!9{!:_!:e!:h!:k!:n!:v!;gPPPPPPPPP!;j!;yPPPP!V!>`!?[!?_]jOs#v$w*W,d(TeOTYZ[fistuwy}!O!S!U!V!W!Z!^!h!i!j!k!l!m!n!p!t!u!v!x!y#P#T#X#Y#c#g#j#m#s#v$X$Y$[$^$a$r$t$u$w%O%[%a%h%k%m%p%t%y%{&V&b&d&o&s&|'O'P'W'Z'_'b'i'l'}(O(R(T(U(Y(_(a(e(i(n(o(u(x)V)X)a)d)p)w)y)}*O*S*W*^*b*l*v*y*z*}+T+U+W+Y+]+^+a+d+h+i+l+t+v+w,O,],^,d,l,m,p,z,{,|-O-P-S-U-W-Y-[-^-_-b-y-{.S.V.Y.}/O/o/s0[0z0{0|0}1P1Q1R1S1T1V1Z}!hQ#r$P$b$q$}%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1O!P!iQ#r$P$b$q$}%S%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1O!R!jQ#r$P$b$q$}%S%T%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1O!T!kQ#r$P$b$q$}%S%T%U%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1O!V!lQ#r$P$b$q$}%S%T%U%V%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1O!X!mQ#r$P$b$q$}%S%T%U%V%W%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1O!]!mQ!s#r$P$b$q$}%S%T%U%V%W%X%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1O(TTOTYZ[fistuwy}!O!S!U!V!W!Z!^!h!i!j!k!l!m!n!p!t!u!v!x!y#P#T#X#Y#c#g#j#m#s#v$X$Y$[$^$a$r$t$u$w%O%[%a%h%k%m%p%t%y%{&V&b&d&o&s&|'O'P'W'Z'_'b'i'l'}(O(R(T(U(Y(_(a(e(i(n(o(u(x)V)X)a)d)p)w)y)}*O*S*W*^*b*l*v*y*z*}+T+U+W+Y+]+^+a+d+h+i+l+t+v+w,O,],^,d,l,m,p,z,{,|-O-P-S-U-W-Y-[-^-_-b-y-{.S.V.Y.}/O/o/s0[0z0{0|0}1P1Q1R1S1T1V1Z&iVOYZ[isuw}!O!S!U!V!Z!n!p!t!u!v!x!y#c#g#j#m#s#v$Y$[$^$a$u$w%[%a%h%k%m%t%y%{&V&b&o&s'O'P'W'Z'b'i'l'}(O(R(T(U(Y(a(i(o(u(x)V)X)a)p)w)y*S*W*^*b*l*v*y*z*}+T+U+W+Y+]+^+a+h+i+l+t+w,O,d,l,m,p,z,{,|-O-P-S-U-W-Y-[-^-_-b-y-{.S.V.Y.}/O/s0[0z0{0|0}1P1Q1R1S1V1Z%sXOYZ[isw}!O!S!U!V!Z!n!p#c#g#j#m#s#v$Y$[$^$a$u$w%[%a%k%m%t%y%{&V&b&o&s'O'P'W'Z'b'i'l'}(O(R(T(U(Y(a(i(o(u(x)V)X)a)p)w)y*S*W*^*b*l*v*y*z*}+T+W+Y+]+^+a+h+i+l+t+w,O,d,l,m,p,z,{,|-O-P-S-W-Y-[-^-_-b-y-{.S.V.}/O/s1Q1R1SQ$VvQ/t/SR1W1Y'zeOTYZ[fistuwy}!O!S!U!V!W!Z!^!h!i!j!k!l!m!p!t!u!v!x!y#P#T#X#Y#c#g#j#m#s#v$X$Y$[$^$a$r$t$u$w%O%[%a%h%k%m%p%t%y%{&V&b&d&o&s&|'O'P'W'Z'_'b'i'l'}(R(T(U(Y(_(a(e(i(n(o(u(x)V)X)a)d)p)w)y)}*O*S*W*^*b*l*y*z*}+T+U+W+Y+]+^+a+d+h+i+l+t+v+w,O,],^,d,l,m,p,{,|-O-P-S-U-W-Y-[-^-_-b-y-{.S.V.Y.}/O/o/s0[0z0{0|0}1P1Q1R1S1T1V1ZW#ym!P!Q$hW$Rv&q/S1YQ$j!RQ$n!TQ${![Q$|!]W%Z!n(O*v,zS&p$S$TQ'e$vQ)Y&jQ)h'QU)i'S)j)kU)l'U)m+}W)s'Y,Q-j.dQ*d'nW*e'p,s-}.lQ,P)rS,r*f*gY-d+x-e.a.b/XQ-g+zQ-t,hQ-x,kQ.j-vl.o.R.u.v.x/d/f/k0R0W0]0b0m0r0uQ/W.`Q/l.wQ/x/^Q0T/hU0h0^0k0sX0n0c0o0v0wR&o$R!_!|YZ!U!V!p%a%m%t(R(T(U(a(i)y*y*z*}+T+W+Y,{,|-O-P-S.S.V.}/O/sR%k!{Q#QYQ&W#cQ&Z#gQ&]#jQ&_#mQ&x$^Q&{$aR-`+lT/R.Y0[![!oQ!s#r$P$b$q$}%S%T%U%V%W%X%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1OQ&m#zQ't$|R*p'uR'}%ZQ%d!rR/v/[(SdOTYZ[fistuwy}!O!S!U!V!W!Z!^!h!i!j!k!l!m!n!p!t!u!v!x!y#P#T#X#Y#c#g#j#m#s#v$X$Y$[$^$a$r$t$u$w%O%[%a%h%k%m%p%t%y%{&V&b&d&o&s&|'O'P'W'Z'_'b'i'l'}(O(R(T(U(Y(_(a(e(i(n(o(u(x)V)X)a)d)p)w)y)}*O*S*W*^*b*l*v*y*z*}+T+U+W+Y+]+^+a+d+h+i+l+t+v+w,O,],^,d,l,m,p,z,{,|-O-P-S-U-W-Y-[-^-_-b-y-{.S.V.Y.}/O/o/s0[0z0{0|0}1P1Q1R1S1T1V1ZS#pd#q!P.s.R.u.v.w.x/^/d/f/k0R0W0]0^0b0c0k0m0o0r0s0u0v0w(SdOTYZ[fistuwy}!O!S!U!V!W!Z!^!h!i!j!k!l!m!n!p!t!u!v!x!y#P#T#X#Y#c#g#j#m#s#v$X$Y$[$^$a$r$t$u$w%O%[%a%h%k%m%p%t%y%{&V&b&d&o&s&|'O'P'W'Z'_'b'i'l'}(O(R(T(U(Y(_(a(e(i(n(o(u(x)V)X)a)d)p)w)y)}*O*S*W*^*b*l*v*y*z*}+T+U+W+Y+]+^+a+d+h+i+l+t+v+w,O,],^,d,l,m,p,z,{,|-O-P-S-U-W-Y-[-^-_-b-y-{.S.V.Y.}/O/o/s0[0z0{0|0}1P1Q1R1S1T1V1ZT#pd#qT#d`#ee(|&W&Z&]&_)O)Q)S)U-`._T+m({+nT#ha#iT#kb#lT#nc#oQ$`xQ,P)sR,q*eX$^x$_$`&zQ'[$nQ'r${Q'u$|R*V'eQ)t'YV-i,Q-j.dZlOs$w*W,dXpOs*W,dQ$x!YQ']$oQ'^$pQ'o$zQ's$|Q*T'dQ*['iQ*_'jQ*`'kQ*m'qS*o't'uQ,W)yQ,Y)zQ,Z){Q,_*RS,a*U*nQ,e*YQ,f*ZS,g*]*^Q,w*pQ-l,VQ-m,XQ-o,`S-p,b,cQ-u,iQ-w,jQ.e-nQ.g-qQ.h-sQ.i-tQ/Y.fQ/Z.jQ/p.{R0Z/qWpOs*W,dR#|oQ'q${S*U'e'rR,c*VQ,p*eR-{,qQ*n'qQ,b*UR-q,cZnOos*W,dQ'w$}R*r'xT.P,x.Qu.z.R.u.v.x/^/d/f/k0R0W0]0^0b0k0m0r0s0ut.z.R.u.v.x/^/d/f/k0R0W0]0^0b0k0m0r0s0uQ/l.wX0n0c0o0v0w!P.r.R.u.v.w.x/^/d/f/k0R0W0]0^0b0c0k0m0o0r0s0u0v0wQ/a.qR/}/bg/d.t/e/y0Q0V0e0g0i0t0x0yu.y.R.u.v.x/^/d/f/k0R0W0]0^0b0k0m0r0s0uX/_.o.y/x0hR/z/^V0j0^0k0sR/q.{QsOS$Os,dR,d*WQ&r$UR)_&rS%z#W$WS(p%z(sT(s%}&tQ%n#OQ%u#SW(b%n%u(g(kQ(g%rR(k%wQ&}$bR)e&}Q(v&OQ+_(qT+e(v+_Q(P%]R*w(PS(S%`%aY*{(S*|-Q.W/PU*|(T(U(VU-Q*}+O+PS.W-R-SR/P.XQ#_^R&R#_Q#b_R&T#bQ#e`R&X#eQ(y&US+j(y+kR+k(zQ+n({R-a+nQ#iaR&[#iQ#lbR&^#lQ#ocR&`#oQ#qdR&a#qQ#tgQ&c#rW&f#t&c)b+uQ)b&wR+u1OQ$_xS&y$_&zR&z$`Q'X$lR)q'XQ&k#yR)Z&kQ$h!QR'R$hQ+y)iS-f+y.cR.c-gQ'V$jR)n'VQ,R)tR-k,RQ#wkR&h#wQ)x']R,U)xQ'`$qS*P'`*QR*Q'aQ'h$xR*X'hQ'm$yS*c'm,nR,n*dQ,t*iR.O,tWoOs*W,dR#{oQ.Q,xR.m.Qd/e.t/y0Q0V0e0g0i0t0x0yR0P/eU/].o/x0hR/w/]Q0d0VS0p0d0qR0q0eS0_/y/zR0l0_Q/g.tR0S/gR!`PXrOs*W,dWqOs*W,dR'f$wYkOs$w*W,dR&g#v[xOs#v$w*W,dR&x$^&hQOYZ[isuw}!O!S!U!V!Z!n!p!t!u!v!x!y#c#g#j#m#s#v$Y$[$^$a$u$w%[%a%h%k%m%t%y%{&V&b&o&s'O'P'W'Z'b'i'l'}(O(R(T(U(Y(a(i(o(u(x)V)X)a)p)w)y*S*W*^*b*l*v*y*z*}+T+U+W+Y+]+^+a+h+i+l+t+w,O,d,l,m,p,z,{,|-O-P-S-U-W-Y-[-^-_-b-y-{.S.V.Y.}/O/s0[0z0{0|0}1P1Q1R1S1V1ZQ!sTQ#rfQ$PtU$by%p(eS$q!W$tQ$}!^Q%S!hQ%T!iQ%U!jQ%V!kQ%W!lQ%X!mQ%r#PQ%w#TQ%}#XQ&O#YQ&t$XQ'a$rQ'x%OQ)W&dU)c&|)d+vW)|'_*O,],^Q+R(_Q+[(nQ,[)}Q-Z+dQ0Y/oR1O1TQ#OYQ#SZQ$o!UQ$p!VQ%`!pQ(V%a^(^%m%t(a(i+T+W+Y^*x(R*z-O-P.V/O/sQ+O(TQ+P(UQ,X)yQ,}*yQ-R*}Q.T,{Q.U,|Q.X-SQ.|.SR/r.}[gOs#v$w*W,d!^!{YZ!U!V!p%a%m%t(R(T(U(a(i)y*y*z*}+T+W+Y,{,|-O-P-S.S.V.}/O/sQ#W[Q#uiS$Ww}Q$e!OW$l!S$a'b*SS$y!Z$uW%Y!n(O*v,zY&U#c#g#j#m+l`&e#s&b)V)X)a+t-b1SQ&u$YQ&v$[Q&w$^Q'{%[Q(]%kW(m%y(o+]+aQ(q%{Q(z&VQ)]&oS)`&s1QQ)f'OQ)g'PU)o'W)p,OQ)v'ZQ*]'iY*a'l*b,l,m-yQ*t'}S+Q(Y1RW+c(u+^-W-[W+g(x+i-^-_Q,T)wQ,i*^Q,v*lQ-]+hQ-c+wQ-z,pQ.]-YR.k-{hUOs#s#v$w&b&s(Y)V)X*W,d%Y!zYZ[iw}!O!S!U!V!Z!n!p#c#g#j#m$Y$[$^$a$u%[%a%k%m%t%y%{&V&o'O'P'W'Z'b'i'l'}(O(R(T(U(a(i(o(u(x)a)p)w)y*S*^*b*l*v*y*z*}+T+W+Y+]+^+a+h+i+l+t+w,O,l,m,p,z,{,|-O-P-S-W-Y-[-^-_-b-y-{.S.V.}/O/s1Q1R1SQ$QuW%e!t!x0{1VQ%f!uQ%g!vQ%i!yQ%s0zS(X%h1PQ(Z0|Q([0}Q-T+UQ.[-US/Q.Y0[R1X1ZU$Uv/S1YR)^&q[hOs#v$w*W,da!}Y#c#g#j#m$^$a+lQ#][Q$ZwR$d}Q%o#OQ%v#SQ%|#WQ'{%YQ(h%rQ(l%wQ(t%}Q(w&OQ+`(qQ,y*tQ.Z-TQ/U.[R/u/TQ$cyQ(d%pR+V(eQ/T.YR0f0[R#VZR#[[R%_!nQ%]!nV*u(O*v,z!]!qQ!s#r$P$b$q$}%S%T%U%V%W%X%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1OR%b!pQ&W#cQ&Z#gQ&]#jQ&_#mR-`+lQ(}&WQ)P&ZQ)R&]Q)T&_Q+p)OQ+q)QQ+r)SQ+s)UQ.^-`R/V._Q$m!SQ&{$aQ*R'bR,`*SQ#zmQ$f!PQ$i!QR'T$hQ)h'SR+|)kQ)h'SQ+{)jR+|)kR$k!RR)u'YXqOs*W,dQ$s!WR'c$tQ$z!ZR'd$uR*k'pQ*i'pV-|,s-}.lQ.{.RQ/i.uR/j.vU.t.R.u.vQ/n.xQ/y/^Q0O/dU0Q/f0R0bQ0V/kQ0e0WQ0g0]U0i0^0k0sQ0t0mQ0x0rR0y0uR/m.wR/{/^",nodeNames:"⚠ print { { { { Comment Script AssignStatement * BinaryExpression BitOp BitOp BitOp BitOp ArithOp ArithOp @ ArithOp ** UnaryExpression ArithOp BitOp AwaitExpression await ) ( ParenthesizedExpression BinaryExpression or and CompareOp in not is UnaryExpression ConditionalExpression if else LambdaExpression lambda ParamList VariableName AssignOp , : NamedExpression AssignOp YieldExpression yield from TupleExpression ComprehensionExpression async for LambdaExpression ] [ ArrayExpression ArrayComprehensionExpression } { DictionaryExpression DictionaryComprehensionExpression SetExpression SetComprehensionExpression CallExpression ArgList AssignOp MemberExpression . PropertyName Number String FormatString FormatReplacement FormatConversion FormatSpec FormatReplacement FormatReplacement FormatReplacement FormatReplacement ContinuedString Ellipsis None Boolean TypeDef AssignOp UpdateStatement UpdateOp ExpressionStatement DeleteStatement del PassStatement pass BreakStatement break ContinueStatement continue ReturnStatement return YieldStatement PrintStatement RaiseStatement raise ImportStatement import as ScopeStatement global nonlocal AssertStatement assert TypeDefinition type TypeParamList TypeParam StatementGroup ; IfStatement Body elif WhileStatement while ForStatement TryStatement try except finally WithStatement with FunctionDefinition def ParamList AssignOp TypeDef ClassDefinition class DecoratedStatement Decorator At MatchStatement match MatchBody MatchClause case CapturePattern LiteralPattern ArithOp ArithOp AsPattern OrPattern LogicOp AttributePattern SequencePattern MappingPattern StarPattern ClassPattern PatternArgList KeywordPattern KeywordPattern Guard",maxTerm:283,context:q,nodeProps:[["group",-15,8,88,90,91,93,95,97,99,101,102,103,105,108,111,113,"Statement Statement",-22,10,20,23,27,42,51,52,58,59,62,63,64,65,66,69,72,73,74,82,83,84,85,"Expression",-10,117,119,122,124,125,129,131,136,138,141,"Statement",-9,146,147,150,151,153,154,155,156,157,"Pattern"],["openedBy",25,"(",56,"[",60,"{"],["closedBy",26,")",57,"]",61,"}"]],propSources:[m],skippedNodes:[0,6],repeatNodeCount:38,tokenData:"%-W#sR!`OX%TXY=|Y[%T[]=|]p%Tpq=|qr@_rsDOst!+|tu%Tuv!Nnvw#!|wx#$Wxy#:Uyz#;Yz{#<^{|#>x|}#@S}!O#AW!O!P#Ci!P!Q#N_!Q!R$!y!R![$&w![!]$1e!]!^$3s!^!_$4w!_!`$7c!`!a$8m!a!b%T!b!c$;U!c!d$W!e!h$W#V#Y$Q<%lO$Xc&r!b&jS&mW%p!TOX%TXY=|Y[%T[]=|]p%Tpq=|qr%Trs&Vsw%Twx/Xx#O%T#O#P?d#P#o%T#o#p8^#p#q%T#q#r8^#r;'S%T;'S;=`=v<%lO%T#s?i[&r!bOY%TYZ=|Z]%T]^=|^#o%T#o#p8^#p#q%T#q#r8^#r;'S%T;'S;=`=P;=`<%l8^<%lO%T!q@hd&r!b&jS&mWOr%Trs&Vsw%Twx/Xx!_%T!_!`Av!`#O%T#O#P7o#P#T%T#T#UBz#U#f%T#f#gBz#g#hBz#h#o%T#o#p8^#p#q%T#q#r8^#r;'S%T;'S;=`=v<%lO%T!qBR]oR&r!b&jS&mWOr%Trs&Vsw%Twx/Xx#O%T#O#P7o#P#o%T#o#p8^#p#q%T#q#r8^#r;'S%T;'S;=`=v<%lO%T!qCV]!nR&r!b&jS&mWOr%Trs&Vsw%Twx/Xx#O%T#O#P7o#P#o%T#o#p8^#p#q%T#q#r8^#r;'S%T;'S;=`=v<%lO%T#cDXa&r!b&jS&hsOYE^YZ%TZ]E^]^%T^rE^rs!)|swE^wxGpx#OE^#O#P!!u#P#oE^#o#p!#d#p#qE^#q#r!#d#r;'SE^;'S;=`!)v<%lOE^#cEia&r!b&jS&mW&hsOYE^YZ%TZ]E^]^%T^rE^rsFnswE^wxGpx#OE^#O#P!!u#P#oE^#o#p!#d#p#qE^#q#r!#d#r;'SE^;'S;=`!)v<%lOE^#cFw]&r!b&jS&hsOr%Trs'Vsw%Twx/Xx#O%T#O#P7o#P#o%T#o#p8^#p#q%T#q#r8^#r;'S%T;'S;=`=v<%lO%T#cGya&r!b&mW&hsOYE^YZ%TZ]E^]^%T^rE^rsFnswE^wxIOx#OE^#O#P!!u#P#oE^#o#p!#d#p#qE^#q#r!#d#r;'SE^;'S;=`!)v<%lOE^#cIXa&r!b&mW&hsOYE^YZ%TZ]E^]^%T^rE^rsFnswE^wxJ^x#OE^#O#P!!u#P#oE^#o#p!#d#p#qE^#q#r!#d#r;'SE^;'S;=`!)v<%lOE^#_Jg_&r!b&mW&hsOYJ^YZ1XZ]J^]^1X^rJ^rsKfs#OJ^#O#PL`#P#oJ^#o#pL}#p#qJ^#q#rL}#r;'SJ^;'S;=`!!o<%lOJ^#_KmZ&r!b&hsOr1Xrs2ys#O1X#O#P3q#P#o1X#o#p4`#p#q1X#q#r4`#r;'S1X;'S;=`7i<%lO1X#_LeW&r!bO#oJ^#o#pL}#p#qJ^#q#rL}#r;'SJ^;'S;=`! r;=`<%lL}<%lOJ^{MUZ&mW&hsOYL}YZ4`Z]L}]^4`^rL}rsMws#OL}#O#PNc#P;'SL};'S;=`! l<%lOL}{M|V&hsOr4`rs5ds#O4`#O#P5y#P;'S4`;'S;=`6t<%lO4`{NfRO;'SL};'S;=`No;=`OL}{Nv[&mW&hsOYL}YZ4`Z]L}]^4`^rL}rsMws#OL}#O#PNc#P;'SL};'S;=`! l;=`<%lL}<%lOL}{! oP;=`<%lL}#_! y[&mW&hsOYL}YZ4`Z]L}]^4`^rL}rsMws#OL}#O#PNc#P;'SL};'S;=`! l;=`<%lJ^<%lOL}#_!!rP;=`<%lJ^#c!!zW&r!bO#oE^#o#p!#d#p#qE^#q#r!#d#r;'SE^;'S;=`!(q;=`<%l!#d<%lOE^!P!#m]&jS&mW&hsOY!#dYZ8^Z]!#d]^8^^r!#drs!$fsw!#dwx!%Yx#O!#d#O#P!'Y#P;'S!#d;'S;=`!(k<%lO!#d!P!$mX&jS&hsOr8^rs9rsw8^wx:dx#O8^#O#P;v#P;'S8^;'S;=`^s#O!=U#O#P!@j#P#o!=U#o#p!Ag#p#q!=U#q#r!Ag#r;'S!=U;'S;=`!FQ<%lO!=U#o!>e_U!T&r!bOY!=UYZ1XZ]!=U]^1X^r!=Urs!?ds#O!=U#O#P!@j#P#o!=U#o#p!Ag#p#q!=U#q#r!Ag#r;'S!=U;'S;=`!FQ<%lO!=U#o!?k_U!T&r!bOY!=UYZ1XZ]!=U]^1X^r!=Urs!3`s#O!=U#O#P!@j#P#o!=U#o#p!Ag#p#q!=U#q#r!Ag#r;'S!=U;'S;=`!FQ<%lO!=U#o!@q[U!T&r!bOY!=UYZ1XZ]!=U]^1X^#o!=U#o#p!Ag#p#q!=U#q#r!Ag#r;'S!=U;'S;=`!Ec;=`<%l4`<%lO!=U!]!AnZU!T&mWOY!AgYZ4`Z]!Ag]^4`^r!Agrs!Bas#O!Ag#O#P!DP#P;'S!Ag;'S;=`!E]<%lO!Ag!]!BfZU!TOY!AgYZ4`Z]!Ag]^4`^r!Agrs!CXs#O!Ag#O#P!DP#P;'S!Ag;'S;=`!E]<%lO!Ag!]!C^ZU!TOY!AgYZ4`Z]!Ag]^4`^r!Agrs!4Ys#O!Ag#O#P!DP#P;'S!Ag;'S;=`!E]<%lO!Ag!]!DUWU!TOY!AgYZ4`Z]!Ag]^4`^;'S!Ag;'S;=`!Dn;=`<%l4`<%lO!Ag!]!DsW&mWOr4`rs4zs#O4`#O#P5y#P;'S4`;'S;=`6t;=`<%l!Ag<%lO4`!]!E`P;=`<%l!Ag#o!EhW&mWOr4`rs4zs#O4`#O#P5y#P;'S4`;'S;=`6t;=`<%l!=U<%lO4`#o!FTP;=`<%l!=U#s!F_[U!T&r!bOY!+|YZ%TZ]!+|]^%T^#o!+|#o#p!GT#p#q!+|#q#r!GT#r;'S!+|;'S;=`!Mq;=`<%l8^<%lO!+|!a!G^]U!T&jS&mWOY!GTYZ8^Z]!GT]^8^^r!GTrs!HVsw!GTwx!JVx#O!GT#O#P!LV#P;'S!GT;'S;=`!Mk<%lO!GT!a!H^]U!T&jSOY!GTYZ8^Z]!GT]^8^^r!GTrs!IVsw!GTwx!JVx#O!GT#O#P!LV#P;'S!GT;'S;=`!Mk<%lO!GT!a!I^]U!T&jSOY!GTYZ8^Z]!GT]^8^^r!GTrs!5wsw!GTwx!JVx#O!GT#O#P!LV#P;'S!GT;'S;=`!Mk<%lO!GT!a!J^]U!T&mWOY!GTYZ8^Z]!GT]^8^^r!GTrs!HVsw!GTwx!KVx#O!GT#O#P!LV#P;'S!GT;'S;=`!Mk<%lO!GT!a!K^]U!T&mWOY!GTYZ8^Z]!GT]^8^^r!GTrs!HVsw!GTwx!Agx#O!GT#O#P!LV#P;'S!GT;'S;=`!Mk<%lO!GT!a!L[WU!TOY!GTYZ8^Z]!GT]^8^^;'S!GT;'S;=`!Lt;=`<%l8^<%lO!GT!a!L{Y&jS&mWOr8^rs9Qsw8^wx:dx#O8^#O#P;v#P;'S8^;'S;=`Q<%lO$TP;=`<%l$ei&r!b&jS&mW&g`&SsOr%Trs$@Ssw%Twx$C`x!Q%T!Q![$Q<%lO$Q<%lO$Q<%lO$Q<%lO$Q<%lO$d[O]||-1}],tokenPrec:7372});var b=a(77120),Z=a(21649),u=a(64100);const y=new Z.hr,W=new Set(["Script","Body","FunctionDefinition","ClassDefinition","LambdaExpression","ForStatement","MatchClause"]);function V(O){return(r,a,Q)=>{if(Q)return!1;let i=r.node.getChild("VariableName");return i&&a(i,O),!0}}const R={FunctionDefinition:V("function"),ClassDefinition:V("class"),ForStatement(O,r,a){if(a)for(let a=O.node.firstChild;a;a=a.nextSibling)if("VariableName"==a.name)r(a,"variable");else if("in"==a.name)break},ImportStatement(O,r){var a,Q;let{node:i}=O,x="from"==(null===(a=i.firstChild)||void 0===a?void 0:a.name);for(let O=i.getChild("import");O;O=O.nextSibling)"VariableName"==O.name&&"as"!=(null===(Q=O.nextSibling)||void 0===Q?void 0:Q.name)&&r(O,x?"variable":"namespace")},AssignStatement(O,r){for(let a=O.node.firstChild;a;a=a.nextSibling)if("VariableName"==a.name)r(a,"variable");else if(":"==a.name||"AssignOp"==a.name)break},ParamList(O,r){for(let a=null,Q=O.node.firstChild;Q;Q=Q.nextSibling)"VariableName"!=Q.name||a&&/\*|AssignOp/.test(a.name)||r(Q,"variable"),a=Q},CapturePattern:V("variable"),AsPattern:V("variable"),__proto__:null};function v(O,r){let a=y.get(r);if(a)return a;let Q=[],i=!0;function x(r,a){let i=O.sliceString(r.from,r.to);Q.push({label:i,type:a})}return r.cursor(Z.vj.IncludeAnonymous).iterate((r=>{if(r.name){let O=R[r.name];if(O&&O(r,x,i)||!i&&W.has(r.name))return!1;i=!1}else if(r.to-r.from>8192){for(let a of v(O,r.node))Q.push(a);return!1}})),y.set(r,Q),Q}const j=/^[\w\xa1-\uffff][\w\d\xa1-\uffff]*$/,G=["String","FormatString","Comment","PropertyName"];function h(O){let r=(0,b.qz)(O.state).resolveInner(O.pos,-1);if(G.indexOf(r.name)>-1)return null;let a="VariableName"==r.name||r.to-r.from<20&&j.test(O.state.sliceDoc(r.from,r.to));if(!a&&!O.explicit)return null;let Q=[];for(let a=r;a;a=a.parent)W.has(a.name)&&(Q=Q.concat(v(O.state.doc,a)));return{options:Q,from:a?r.from:O.pos,validFor:j}}const _=["__annotations__","__builtins__","__debug__","__doc__","__import__","__name__","__loader__","__package__","__spec__","False","None","True"].map((O=>({label:O,type:"constant"}))).concat(["ArithmeticError","AssertionError","AttributeError","BaseException","BlockingIOError","BrokenPipeError","BufferError","BytesWarning","ChildProcessError","ConnectionAbortedError","ConnectionError","ConnectionRefusedError","ConnectionResetError","DeprecationWarning","EOFError","Ellipsis","EncodingWarning","EnvironmentError","Exception","FileExistsError","FileNotFoundError","FloatingPointError","FutureWarning","GeneratorExit","IOError","ImportError","ImportWarning","IndentationError","IndexError","InterruptedError","IsADirectoryError","KeyError","KeyboardInterrupt","LookupError","MemoryError","ModuleNotFoundError","NameError","NotADirectoryError","NotImplemented","NotImplementedError","OSError","OverflowError","PendingDeprecationWarning","PermissionError","ProcessLookupError","RecursionError","ReferenceError","ResourceWarning","RuntimeError","RuntimeWarning","StopAsyncIteration","StopIteration","SyntaxError","SyntaxWarning","SystemError","SystemExit","TabError","TimeoutError","TypeError","UnboundLocalError","UnicodeDecodeError","UnicodeEncodeError","UnicodeError","UnicodeTranslateError","UnicodeWarning","UserWarning","ValueError","Warning","ZeroDivisionError"].map((O=>({label:O,type:"type"})))).concat(["bool","bytearray","bytes","classmethod","complex","float","frozenset","int","list","map","memoryview","object","range","set","staticmethod","str","super","tuple","type"].map((O=>({label:O,type:"class"})))).concat(["abs","aiter","all","anext","any","ascii","bin","breakpoint","callable","chr","compile","delattr","dict","dir","divmod","enumerate","eval","exec","exit","filter","format","getattr","globals","hasattr","hash","help","hex","id","input","isinstance","issubclass","iter","len","license","locals","max","min","next","oct","open","ord","pow","print","property","quit","repr","reversed","round","setattr","slice","sorted","sum","vars","zip"].map((O=>({label:O,type:"function"})))),k=[(0,u.Gn)("def ${name}(${params}):\n\t${}",{label:"def",detail:"function",type:"keyword"}),(0,u.Gn)("for ${name} in ${collection}:\n\t${}",{label:"for",detail:"loop",type:"keyword"}),(0,u.Gn)("while ${}:\n\t${}",{label:"while",detail:"loop",type:"keyword"}),(0,u.Gn)("try:\n\t${}\nexcept ${error}:\n\t${}",{label:"try",detail:"/ except block",type:"keyword"}),(0,u.Gn)("if ${}:\n\t\n",{label:"if",detail:"block",type:"keyword"}),(0,u.Gn)("if ${}:\n\t${}\nelse:\n\t${}",{label:"if",detail:"/ else block",type:"keyword"}),(0,u.Gn)("class ${name}:\n\tdef __init__(self, ${params}):\n\t\t\t${}",{label:"class",detail:"definition",type:"keyword"}),(0,u.Gn)("import ${module}",{label:"import",detail:"statement",type:"keyword"}),(0,u.Gn)("from ${module} import ${names}",{label:"from",detail:"import",type:"keyword"})],g=(0,u.eC)(G,(0,u.Mb)(_.concat(k)));function E(O,r){let a=O.baseIndentFor(r),Q=O.lineAt(O.pos,-1),i=Q.from+Q.text.length;return/^\s*($|#)/.test(Q.text)&&O.node.toa?null:a+O.unit}const U=b.qp.define({name:"python",parser:f.configure({props:[b.uj.add({Body:O=>{var r;return null!==(r=E(O,O.node))&&void 0!==r?r:O.continue()},IfStatement:O=>/^\s*(else:|elif )/.test(O.textAfter)?O.baseIndent:O.continue(),TryStatement:O=>/^\s*(except |finally:|else:)/.test(O.textAfter)?O.baseIndent:O.continue(),"TupleExpression ComprehensionExpression ParamList ArgList ParenthesizedExpression":(0,b.vw)({closing:")"}),"DictionaryExpression DictionaryComprehensionExpression SetExpression SetComprehensionExpression":(0,b.vw)({closing:"}"}),"ArrayExpression ArrayComprehensionExpression":(0,b.vw)({closing:"]"}),"String FormatString":()=>null,Script:O=>{if(O.pos+/\s*/.exec(O.textAfter)[0].length>=O.node.to){let r=null;for(let a=O.node,Q=a.to;a=a.lastChild,a&&a.to==Q;)"Body"==a.type.name&&(r=a);if(r){let a=E(O,r);if(null!=a)return a}}return O.continue()}}),b.x0.add({"ArrayExpression DictionaryExpression SetExpression TupleExpression":b.Dv,Body:(O,r)=>({from:O.from+1,to:O.to-(O.to==r.doc.length?0:1)})})]}),languageData:{closeBrackets:{brackets:["(","[","{","'",'"',"'''",'"""'],stringPrefixes:["f","fr","rf","r","u","b","br","rb","F","FR","RF","R","U","B","BR","RB"]},commentTokens:{line:"#"},indentOnInput:/^\s*([\}\]\)]|else:|elif |except |finally:)$/}});function z(){return new b.ri(U,[U.data.of({autocomplete:h}),U.data.of({autocomplete:g})])}}}]);
+//# sourceMappingURL=2377.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/2377.index.js.map b/book/_build/html/_static/2377.index.js.map
new file mode 100644
index 0000000..a87a062
--- /dev/null
+++ b/book/_build/html/_static/2377.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"2377.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@lezer/python/dist/index.js","webpack://thebe/../../node_modules/@codemirror/lang-python/dist/index.js"],"sourcesContent":["import { ExternalTokenizer, ContextTracker, LRParser } from '@lezer/lr';\nimport { styleTags, tags } from '@lezer/highlight';\n\n// This file was generated by lezer-generator. You probably shouldn't edit it.\nconst printKeyword = 1,\n indent = 201,\n dedent = 202,\n newline$1 = 203,\n blankLineStart = 204,\n newlineBracketed = 205,\n eof = 206,\n formatString1Content = 207,\n formatString1Brace = 2,\n formatString1End = 208,\n formatString2Content = 209,\n formatString2Brace = 3,\n formatString2End = 210,\n formatString1lContent = 211,\n formatString1lBrace = 4,\n formatString1lEnd = 212,\n formatString2lContent = 213,\n formatString2lBrace = 5,\n formatString2lEnd = 214,\n ParenL = 26,\n ParenthesizedExpression = 27,\n TupleExpression = 51,\n ComprehensionExpression = 52,\n BracketL = 57,\n ArrayExpression = 58,\n ArrayComprehensionExpression = 59,\n BraceL = 61,\n DictionaryExpression = 62,\n DictionaryComprehensionExpression = 63,\n SetExpression = 64,\n SetComprehensionExpression = 65,\n ArgList = 67,\n subscript = 251,\n FormatString = 74,\n importList = 270,\n TypeParamList = 115,\n ParamList = 133,\n SequencePattern = 154,\n MappingPattern = 155,\n PatternArgList = 158;\n\nconst newline = 10, carriageReturn = 13, space = 32, tab = 9, hash = 35, parenOpen = 40, dot = 46,\n braceOpen = 123, singleQuote = 39, doubleQuote = 34, backslash = 92;\n\nconst bracketed = new Set([\n ParenthesizedExpression, TupleExpression, ComprehensionExpression, importList, ArgList, ParamList,\n ArrayExpression, ArrayComprehensionExpression, subscript,\n SetExpression, SetComprehensionExpression, FormatString,\n DictionaryExpression, DictionaryComprehensionExpression,\n SequencePattern, MappingPattern, PatternArgList, TypeParamList\n]);\n\nfunction isLineBreak(ch) {\n return ch == newline || ch == carriageReturn\n}\n\nconst newlines = new ExternalTokenizer((input, stack) => {\n let prev;\n if (input.next < 0) {\n input.acceptToken(eof);\n } else if (stack.context.depth < 0) {\n if (isLineBreak(input.next)) input.acceptToken(newlineBracketed, 1);\n } else if (((prev = input.peek(-1)) < 0 || isLineBreak(prev)) &&\n stack.canShift(blankLineStart)) {\n let spaces = 0;\n while (input.next == space || input.next == tab) { input.advance(); spaces++; }\n if (input.next == newline || input.next == carriageReturn || input.next == hash)\n input.acceptToken(blankLineStart, -spaces);\n } else if (isLineBreak(input.next)) {\n input.acceptToken(newline$1, 1);\n }\n}, {contextual: true});\n\nconst indentation = new ExternalTokenizer((input, stack) => {\n let cDepth = stack.context.depth;\n if (cDepth < 0) return\n let prev = input.peek(-1);\n if (prev == newline || prev == carriageReturn) {\n let depth = 0, chars = 0;\n for (;;) {\n if (input.next == space) depth++;\n else if (input.next == tab) depth += 8 - (depth % 8);\n else break\n input.advance();\n chars++;\n }\n if (depth != cDepth &&\n input.next != newline && input.next != carriageReturn && input.next != hash) {\n if (depth < cDepth) input.acceptToken(dedent, -chars);\n else input.acceptToken(indent);\n }\n }\n});\n\nfunction IndentLevel(parent, depth) {\n this.parent = parent;\n // -1 means this is not an actual indent level but a set of brackets\n this.depth = depth;\n this.hash = (parent ? parent.hash + parent.hash << 8 : 0) + depth + (depth << 4);\n}\n\nconst topIndent = new IndentLevel(null, 0);\n\nfunction countIndent(space) {\n let depth = 0;\n for (let i = 0; i < space.length; i++)\n depth += space.charCodeAt(i) == tab ? 8 - (depth % 8) : 1;\n return depth\n}\n\nconst trackIndent = new ContextTracker({\n start: topIndent,\n reduce(context, term) {\n return context.depth < 0 && bracketed.has(term) ? context.parent : context\n },\n shift(context, term, stack, input) {\n if (term == indent) return new IndentLevel(context, countIndent(input.read(input.pos, stack.pos)))\n if (term == dedent) return context.parent\n if (term == ParenL || term == BracketL || term == BraceL) return new IndentLevel(context, -1)\n return context\n },\n hash(context) { return context.hash }\n});\n\nconst legacyPrint = new ExternalTokenizer(input => {\n for (let i = 0; i < 5; i++) {\n if (input.next != \"print\".charCodeAt(i)) return\n input.advance();\n }\n if (/\\w/.test(String.fromCharCode(input.next))) return\n for (let off = 0;; off++) {\n let next = input.peek(off);\n if (next == space || next == tab) continue\n if (next != parenOpen && next != dot && next != newline && next != carriageReturn && next != hash)\n input.acceptToken(printKeyword);\n return\n }\n});\n\nfunction formatString(quote, len, content, brace, end) {\n return new ExternalTokenizer(input => {\n let start = input.pos;\n for (;;) {\n if (input.next < 0) {\n break\n } else if (input.next == braceOpen) {\n if (input.peek(1) == braceOpen) {\n input.advance(2);\n } else {\n if (input.pos == start) {\n input.acceptToken(brace, 1);\n return\n }\n break\n }\n } else if (input.next == backslash) {\n input.advance();\n if (input.next >= 0) input.advance();\n } else if (input.next == quote && (len == 1 || input.peek(1) == quote && input.peek(2) == quote)) {\n if (input.pos == start) {\n input.acceptToken(end, len);\n return\n }\n break\n } else {\n input.advance();\n }\n }\n if (input.pos > start) input.acceptToken(content);\n })\n}\n\nconst formatString1 = formatString(singleQuote, 1, formatString1Content, formatString1Brace, formatString1End);\nconst formatString2 = formatString(doubleQuote, 1, formatString2Content, formatString2Brace, formatString2End);\nconst formatString1l = formatString(singleQuote, 3, formatString1lContent, formatString1lBrace, formatString1lEnd);\nconst formatString2l = formatString(doubleQuote, 3, formatString2lContent, formatString2lBrace, formatString2lEnd);\n\nconst pythonHighlighting = styleTags({\n \"async \\\"*\\\" \\\"**\\\" FormatConversion FormatSpec\": tags.modifier,\n \"for while if elif else try except finally return raise break continue with pass assert await yield match case\": tags.controlKeyword,\n \"in not and or is del\": tags.operatorKeyword,\n \"from def class global nonlocal lambda\": tags.definitionKeyword,\n import: tags.moduleKeyword,\n \"with as print\": tags.keyword,\n Boolean: tags.bool,\n None: tags.null,\n VariableName: tags.variableName,\n \"CallExpression/VariableName\": tags.function(tags.variableName),\n \"FunctionDefinition/VariableName\": tags.function(tags.definition(tags.variableName)),\n \"ClassDefinition/VariableName\": tags.definition(tags.className),\n PropertyName: tags.propertyName,\n \"CallExpression/MemberExpression/PropertyName\": tags.function(tags.propertyName),\n Comment: tags.lineComment,\n Number: tags.number,\n String: tags.string,\n FormatString: tags.special(tags.string),\n UpdateOp: tags.updateOperator,\n \"ArithOp!\": tags.arithmeticOperator,\n BitOp: tags.bitwiseOperator,\n CompareOp: tags.compareOperator,\n AssignOp: tags.definitionOperator,\n Ellipsis: tags.punctuation,\n At: tags.meta,\n \"( )\": tags.paren,\n \"[ ]\": tags.squareBracket,\n \"{ }\": tags.brace,\n \".\": tags.derefOperator,\n \", ;\": tags.separator\n});\n\n// This file was generated by lezer-generator. You probably shouldn't edit it.\nconst spec_identifier = {__proto__:null,await:48, or:58, and:60, in:64, not:66, is:68, if:74, else:76, lambda:80, yield:98, from:100, async:106, for:108, None:168, True:170, False:170, del:184, pass:188, break:192, continue:196, return:200, raise:208, import:212, as:214, global:218, nonlocal:220, assert:224, type:229, elif:242, while:246, try:252, except:254, finally:256, with:260, def:264, class:274, match:285, case:291};\nconst parser = LRParser.deserialize({\n version: 14,\n states: \"#&jO`Q#yOOP$bOSOOO%kQ&nO'#HcOOQS'#Cq'#CqOOQS'#Cr'#CrO'ZQ#xO'#CpO(|Q&nO'#HbOOQS'#Hc'#HcOOQS'#DW'#DWOOQS'#Hb'#HbO)jQ#xO'#DaO)}Q#xO'#DhO*_Q#xO'#DlOOQS'#Dw'#DwO*rO,UO'#DwO*zO7[O'#DwO+SOWO'#DxO+_O`O'#DxO+jOpO'#DxO+uO!bO'#DxO-wQ&nO'#HSOOQS'#HS'#HSO'ZQ#xO'#HRO/ZQ&nO'#HROOQS'#Ee'#EeO/rQ#xO'#EfOOQS'#HQ'#HQO/|Q#xO'#HPOOQV'#HP'#HPO0XQ#xO'#F]OOQS'#Ge'#GeO0^Q#xO'#F[OOQV'#IY'#IYOOQV'#HO'#HOOOQV'#Ft'#FtQ`Q#yOOO'ZQ#xO'#CsO0lQ#xO'#DPO0sQ#xO'#DTO1RQ#xO'#HgO1cQ&nO'#EYO'ZQ#xO'#EZOOQS'#E]'#E]OOQS'#E_'#E_OOQS'#Ea'#EaO1wQ#xO'#EcO2_Q#xO'#EgO0XQ#xO'#EiO2rQ&nO'#EiO0XQ#xO'#ElO/rQ#xO'#EoO0XQ#xO'#EqO/rQ#xO'#EwO/rQ#xO'#EzO2}Q#xO'#E|O3UQ#xO'#FRO3aQ#xO'#E}O/rQ#xO'#FRO0XQ#xO'#FTO0XQ#xO'#FYO3fQ#xO'#F_P3mO#xO'#G}POOO)CBq)CBqOOQS'#Cg'#CgOOQS'#Ch'#ChOOQS'#Ci'#CiOOQS'#Cj'#CjOOQS'#Ck'#CkOOQS'#Cl'#ClOOQS'#Cn'#CnO'ZQ#xO,59QO'ZQ#xO,59QO'ZQ#xO,59QO'ZQ#xO,59QO'ZQ#xO,59QO'ZQ#xO,59QO3xQ#xO'#DqOOQS,5:[,5:[O4]Q#xO'#HqOOQS,5:_,5:_O4jQMlO,5:_O4oQ&nO,59[O0lQ#xO,59dO0lQ#xO,59dO0lQ#xO,59dO7_Q#xO,59dO7dQ#xO,59dO7kQ#xO,59lO7rQ#xO'#HbO8xQ#xO'#HaOOQS'#Ha'#HaOOQS'#D^'#D^O9aQ#xO,59cO'ZQ#xO,59cO9oQ#xO,59cOOQS,59{,59{O9tQ#xO,5:TO'ZQ#xO,5:TOOQS,5:S,5:SO:SQ#xO,5:SO:XQ#xO,5:ZO'ZQ#xO,5:ZO'ZQ#xO,5:XOOQS,5:W,5:WO:jQ#xO,5:WO:oQ#xO,5:YOOOO'#F|'#F|O:tO,UO,5:cOOQS,5:c,5:cOOOO'#F}'#F}O:|O7[O,5:cO;UQ#xO'#DyOOOW'#GO'#GOO;fOWO,5:dOOQS,5:d,5:dO;UQ#xO'#D}OOO`'#GR'#GRO;qO`O,5:dO;UQ#xO'#EOOOOp'#GS'#GSO;|OpO,5:dO;UQ#xO'#EPOOO!b'#GT'#GTOROOQS,5>R,5>RO/rQ#xO'#EUOOQS'#EV'#EVOGZQ#xO'#GWOGkQ#xO,59OOGkQ#xO,59OO)pQ#xO,5:rOGyQ&nO'#HjOOQS,5:u,5:uOOQS,5:},5:}OH^Q#xO,5;ROHoQ#xO,5;TOOQS'#GZ'#GZOH}Q&nO,5;TOI]Q#xO,5;TOIbQ#xO'#IWOOQS,5;W,5;WOIpQ#xO'#ISOOQS,5;Z,5;ZOJRQ#xO,5;]O3aQ#xO,5;cO3aQ#xO,5;fOJZQ&nO'#IZO'ZQ#xO'#IZOJeQ#xO,5;hO2}Q#xO,5;hO/rQ#xO,5;mO0XQ#xO,5;oOJjQ#yO'#ExOKvQ#{O,5;iO! [Q#xO'#I[O3aQ#xO,5;mO! gQ#xO,5;oO! oQ#xO,5;tO! zQ&nO,5;yO'ZQ#xO,5;yPOOO,5=i,5=iP!!ROSO,5=iP!!WO#xO,5=iO!${Q&nO1G.lO!%SQ&nO1G.lO!'sQ&nO1G.lO!'}Q&nO1G.lO!*hQ&nO1G.lO!*{Q&nO1G.lO!+`Q#xO'#HpO!+nQ&nO'#HSO/rQ#xO'#HpO!+xQ#xO'#HoOOQS,5:],5:]O!,QQ#xO,5:]O!,VQ#xO'#HrO!,bQ#xO'#HrO!,uQ#xO,5>]OOQS'#Du'#DuOOQS1G/y1G/yOOQS1G/O1G/OO!-uQ&nO1G/OO!-|Q&nO1G/OO0lQ#xO1G/OO!.iQ#xO1G/WOOQS'#D]'#D]O/rQ#xO,59vOOQS1G.}1G.}O!.pQ#xO1G/gO!/QQ#xO1G/gO!/YQ#xO1G/hO'ZQ#xO'#HiO!/_Q#xO'#HiO!/dQ&nO1G.}O!/tQ#xO,59kO!0zQ#xO,5>XO!1[Q#xO,5>XO!1dQ#xO1G/oO!1iQ&nO1G/oOOQS1G/n1G/nO!1yQ#xO,5>SO!2pQ#xO,5>SO/rQ#xO1G/sO!3_Q#xO1G/uO!3dQ&nO1G/uO!3tQ&nO1G/sOOQS1G/r1G/rOOQS1G/t1G/tOOOO-E9z-E9zOOQS1G/}1G/}OOOO-E9{-E9{O!4UQ#xO'#H|O/rQ#xO'#H|O!4dQ#xO,5:eOOOW-E9|-E9|OOQS1G0O1G0OO!4oQ#xO,5:iOOO`-E:P-E:PO!4zQ#xO,5:jOOOp-E:Q-E:QO!5VQ#xO,5:kOOO!b-E:R-E:ROOQS-E:S-E:SO!5bQ!LUO1G3XO!6RQ&nO1G3XO'ZQ#xO,5oOOQS1G1c1G1cO!7RQ#xO1G1cOOQS'#DX'#DXO/rQ#xO,5>OOOQS,5>O,5>OO!7WQ#xO'#FuO!7cQ#xO,59qO!7kQ#xO1G/ZO!7uQ&nO,5>SOOQS1G3m1G3mOOQS,5:p,5:pO!8fQ#xO'#HROOQS,5UO!9gQ#xO,5>UO/rQ#xO1G0mO/rQ#xO1G0mO0XQ#xO1G0oOOQS-E:X-E:XO!9xQ#xO1G0oO!:TQ#xO1G0oO!:YQ#xO,5>rO!:hQ#xO,5>rO!:vQ#xO,5>nO!;^Q#xO,5>nO!;oQ#xO'#EsO/rQ#xO1G0wO!;zQ#xO1G0wO!uO!BzQ#xO,5>uO!CSQ&nO,5>uO/rQ#xO1G1SO!C^Q#xO1G1SO3aQ#xO1G1XO! gQ#xO1G1ZOOQV,5;d,5;dO!CcQ#zO,5;dO!ChQ#{O1G1TO!F|Q#xO'#GbO3aQ#xO1G1TO3aQ#xO1G1TO!G^Q#xO,5>vO!GkQ#xO,5>vO0XQ#xO,5>vOOQV1G1X1G1XO!GsQ#xO'#FVO!HUQMlO1G1ZO!H^Q#xO1G1ZOOQV1G1`1G1`O3aQ#xO1G1`O!HcQ#xO1G1`O!HkQ#xO'#FaOOQV1G1e1G1eO! zQ&nO1G1ePOOO1G3T1G3TP!HpOSO1G3TOOQS,5>[,5>[OOQS'#Dr'#DrO/rQ#xO,5>[O!HuQ#xO,5>ZO!IYQ#xO,5>ZOOQS1G/w1G/wO!IbQ#xO,5>^O!IrQ#xO,5>^O!IzQ#xO,5>^O!J_Q#xO,5>^O!JoQ#xO,5>^OOQS1G3w1G3wOOQS7+$j7+$jO!7kQ#xO7+$rO!LbQ#xO1G/OO!LiQ#xO1G/OOOQS1G/b1G/bOOQS,5TO'ZQ#xO,5>TOOQS7+$i7+$iO!MVQ#xO7+%RO!M_Q#xO7+%SO!MdQ#xO1G3sOOQS7+%Z7+%ZO!MtQ#xO1G3sO!M|Q#xO7+%ZOOQS,5hO##PQ#xO,5>hO##PQ#xO,5>hO##_O$ISO'#D{O##jO#tO'#H}OOOW1G0P1G0PO##oQ#xO1G0POOO`1G0T1G0TO##wQ#xO1G0TOOOp1G0U1G0UO#$PQ#xO1G0UOOO!b1G0V1G0VO#$XQ#xO1G0VO#$aQ!LUO7+(sO#%QQ&nO1G2]P#%kQ#xO'#GVOOQS,5i,5>iOOOW7+%k7+%kOOO`7+%o7+%oOOOp7+%p7+%pOOO!b7+%q7+%qO#:`Q#xO1G3XO#:yQ#xO1G3XP'ZQ#xO'#FxO/rQ#xO<qO#;mQ#xO,5>qO0XQ#xO,5>qO#pOOQS<sO#sOOQS1G0y1G0yOOQS<xO#DpQ#xO,5>xOOQS,5>x,5>xO#D{Q#xO,5>wO#E^Q#xO,5>wOOQS1G1]1G1]OOQS,5;s,5;sOOQV<XAN>XO#HmQ#xO<eAN>eO/rQ#xO1G2PO#H}Q&nO1G2PP#IXQ#xO'#FyOOQS1G2V1G2VP#IfQ#xO'#GPO#IsQ#xO7+)nO#JZQ#xO,5:hOOOO-E:O-E:OO#JfQ#xO7+(sOOQSAN?_AN?_O#KPQ#xO,5VOOQSANBaANBaOOOO7+%n7+%nOOQS7+'|7+'|O$+jQ#xO<zO$.`Q#xO,5>zO0XQ#xO,5|O$!pQ#xO,5>|OOQS1G1s1G1sO$2WQ&nO,5<_OOQU7+'S7+'SO$$mQ#xO1G/kO$!pQ#xO,5<]O$2_Q#xO,5>}O$2fQ#xO,5>}OOQS1G1v1G1vOOQS7+'V7+'VP$!pQ#xO'#GkO$2nQ#xO1G4hO$2xQ#xO1G4hO$3QQ#xO1G4hOOQS7+%V7+%VO$3`Q#xO1G1wO$3nQ&nO'#FdO$3uQ#xO,5=UOOQS,5=U,5=UO$4TQ#xO1G4iOOQS-E:h-E:hO$!pQ#xO,5=TO$4[Q#xO,5=TO$4aQ#xO7+*SOOQS-E:g-E:gO$4kQ#xO7+*SO$!pQ#xO,5<^P$!pQ#xO'#GjO$4sQ#xO1G2oO$!pQ#xO1G2oP$5RQ#xO'#GiO$5YQ#xO<fPP>i?Z?^PP'a'aPP?vPP'a'aPP'a'a'a'a'a?z@t'aP@wP@}EXHxPH|IYI^IbIf'aPPPIjIs'XP'X'XP'XP'XP'XP'XP'X'X'XP'XPP'XPP'XP'XPIyJVJ_PJfJlPJfPJfJfPPPJfPLzPMTM_MeLzPJfMnPJfPMuM{PNPNe! S! mNPNP! s!!QNPNPNPNP!!f!!l!!o!!t!!w!#R!#X!#e!#w!#}!$X!$_!${!%R!%X!%_!%i!%o!%u!%{!&R!&X!&k!&u!&{!'R!'X!'c!'i!'o!'u!'{!(V!(]!(g!(m!(v!(|!)]!)e!)o!)vPPPPPPPPPPPPPPPPP!)|!*P!*V!*`!*j!*uPPPPPPPPPPPP!/l!1Q!5T!8hPP!8p!9S!9]!:U!9{!:_!:e!:h!:k!:n!:v!;gPPPPPPPPP!;j!;yPPPP!V!>`!?[!?_]jOs#v$w*W,d(TeOTYZ[fistuwy}!O!S!U!V!W!Z!^!h!i!j!k!l!m!n!p!t!u!v!x!y#P#T#X#Y#c#g#j#m#s#v$X$Y$[$^$a$r$t$u$w%O%[%a%h%k%m%p%t%y%{&V&b&d&o&s&|'O'P'W'Z'_'b'i'l'}(O(R(T(U(Y(_(a(e(i(n(o(u(x)V)X)a)d)p)w)y)}*O*S*W*^*b*l*v*y*z*}+T+U+W+Y+]+^+a+d+h+i+l+t+v+w,O,],^,d,l,m,p,z,{,|-O-P-S-U-W-Y-[-^-_-b-y-{.S.V.Y.}/O/o/s0[0z0{0|0}1P1Q1R1S1T1V1Z}!hQ#r$P$b$q$}%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1O!P!iQ#r$P$b$q$}%S%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1O!R!jQ#r$P$b$q$}%S%T%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1O!T!kQ#r$P$b$q$}%S%T%U%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1O!V!lQ#r$P$b$q$}%S%T%U%V%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1O!X!mQ#r$P$b$q$}%S%T%U%V%W%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1O!]!mQ!s#r$P$b$q$}%S%T%U%V%W%X%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1O(TTOTYZ[fistuwy}!O!S!U!V!W!Z!^!h!i!j!k!l!m!n!p!t!u!v!x!y#P#T#X#Y#c#g#j#m#s#v$X$Y$[$^$a$r$t$u$w%O%[%a%h%k%m%p%t%y%{&V&b&d&o&s&|'O'P'W'Z'_'b'i'l'}(O(R(T(U(Y(_(a(e(i(n(o(u(x)V)X)a)d)p)w)y)}*O*S*W*^*b*l*v*y*z*}+T+U+W+Y+]+^+a+d+h+i+l+t+v+w,O,],^,d,l,m,p,z,{,|-O-P-S-U-W-Y-[-^-_-b-y-{.S.V.Y.}/O/o/s0[0z0{0|0}1P1Q1R1S1T1V1Z&iVOYZ[isuw}!O!S!U!V!Z!n!p!t!u!v!x!y#c#g#j#m#s#v$Y$[$^$a$u$w%[%a%h%k%m%t%y%{&V&b&o&s'O'P'W'Z'b'i'l'}(O(R(T(U(Y(a(i(o(u(x)V)X)a)p)w)y*S*W*^*b*l*v*y*z*}+T+U+W+Y+]+^+a+h+i+l+t+w,O,d,l,m,p,z,{,|-O-P-S-U-W-Y-[-^-_-b-y-{.S.V.Y.}/O/s0[0z0{0|0}1P1Q1R1S1V1Z%sXOYZ[isw}!O!S!U!V!Z!n!p#c#g#j#m#s#v$Y$[$^$a$u$w%[%a%k%m%t%y%{&V&b&o&s'O'P'W'Z'b'i'l'}(O(R(T(U(Y(a(i(o(u(x)V)X)a)p)w)y*S*W*^*b*l*v*y*z*}+T+W+Y+]+^+a+h+i+l+t+w,O,d,l,m,p,z,{,|-O-P-S-W-Y-[-^-_-b-y-{.S.V.}/O/s1Q1R1SQ$VvQ/t/SR1W1Y'zeOTYZ[fistuwy}!O!S!U!V!W!Z!^!h!i!j!k!l!m!p!t!u!v!x!y#P#T#X#Y#c#g#j#m#s#v$X$Y$[$^$a$r$t$u$w%O%[%a%h%k%m%p%t%y%{&V&b&d&o&s&|'O'P'W'Z'_'b'i'l'}(R(T(U(Y(_(a(e(i(n(o(u(x)V)X)a)d)p)w)y)}*O*S*W*^*b*l*y*z*}+T+U+W+Y+]+^+a+d+h+i+l+t+v+w,O,],^,d,l,m,p,{,|-O-P-S-U-W-Y-[-^-_-b-y-{.S.V.Y.}/O/o/s0[0z0{0|0}1P1Q1R1S1T1V1ZW#ym!P!Q$hW$Rv&q/S1YQ$j!RQ$n!TQ${![Q$|!]W%Z!n(O*v,zS&p$S$TQ'e$vQ)Y&jQ)h'QU)i'S)j)kU)l'U)m+}W)s'Y,Q-j.dQ*d'nW*e'p,s-}.lQ,P)rS,r*f*gY-d+x-e.a.b/XQ-g+zQ-t,hQ-x,kQ.j-vl.o.R.u.v.x/d/f/k0R0W0]0b0m0r0uQ/W.`Q/l.wQ/x/^Q0T/hU0h0^0k0sX0n0c0o0v0wR&o$R!_!|YZ!U!V!p%a%m%t(R(T(U(a(i)y*y*z*}+T+W+Y,{,|-O-P-S.S.V.}/O/sR%k!{Q#QYQ&W#cQ&Z#gQ&]#jQ&_#mQ&x$^Q&{$aR-`+lT/R.Y0[![!oQ!s#r$P$b$q$}%S%T%U%V%W%X%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1OQ&m#zQ't$|R*p'uR'}%ZQ%d!rR/v/[(SdOTYZ[fistuwy}!O!S!U!V!W!Z!^!h!i!j!k!l!m!n!p!t!u!v!x!y#P#T#X#Y#c#g#j#m#s#v$X$Y$[$^$a$r$t$u$w%O%[%a%h%k%m%p%t%y%{&V&b&d&o&s&|'O'P'W'Z'_'b'i'l'}(O(R(T(U(Y(_(a(e(i(n(o(u(x)V)X)a)d)p)w)y)}*O*S*W*^*b*l*v*y*z*}+T+U+W+Y+]+^+a+d+h+i+l+t+v+w,O,],^,d,l,m,p,z,{,|-O-P-S-U-W-Y-[-^-_-b-y-{.S.V.Y.}/O/o/s0[0z0{0|0}1P1Q1R1S1T1V1ZS#pd#q!P.s.R.u.v.w.x/^/d/f/k0R0W0]0^0b0c0k0m0o0r0s0u0v0w(SdOTYZ[fistuwy}!O!S!U!V!W!Z!^!h!i!j!k!l!m!n!p!t!u!v!x!y#P#T#X#Y#c#g#j#m#s#v$X$Y$[$^$a$r$t$u$w%O%[%a%h%k%m%p%t%y%{&V&b&d&o&s&|'O'P'W'Z'_'b'i'l'}(O(R(T(U(Y(_(a(e(i(n(o(u(x)V)X)a)d)p)w)y)}*O*S*W*^*b*l*v*y*z*}+T+U+W+Y+]+^+a+d+h+i+l+t+v+w,O,],^,d,l,m,p,z,{,|-O-P-S-U-W-Y-[-^-_-b-y-{.S.V.Y.}/O/o/s0[0z0{0|0}1P1Q1R1S1T1V1ZT#pd#qT#d`#ee(|&W&Z&]&_)O)Q)S)U-`._T+m({+nT#ha#iT#kb#lT#nc#oQ$`xQ,P)sR,q*eX$^x$_$`&zQ'[$nQ'r${Q'u$|R*V'eQ)t'YV-i,Q-j.dZlOs$w*W,dXpOs*W,dQ$x!YQ']$oQ'^$pQ'o$zQ's$|Q*T'dQ*['iQ*_'jQ*`'kQ*m'qS*o't'uQ,W)yQ,Y)zQ,Z){Q,_*RS,a*U*nQ,e*YQ,f*ZS,g*]*^Q,w*pQ-l,VQ-m,XQ-o,`S-p,b,cQ-u,iQ-w,jQ.e-nQ.g-qQ.h-sQ.i-tQ/Y.fQ/Z.jQ/p.{R0Z/qWpOs*W,dR#|oQ'q${S*U'e'rR,c*VQ,p*eR-{,qQ*n'qQ,b*UR-q,cZnOos*W,dQ'w$}R*r'xT.P,x.Qu.z.R.u.v.x/^/d/f/k0R0W0]0^0b0k0m0r0s0ut.z.R.u.v.x/^/d/f/k0R0W0]0^0b0k0m0r0s0uQ/l.wX0n0c0o0v0w!P.r.R.u.v.w.x/^/d/f/k0R0W0]0^0b0c0k0m0o0r0s0u0v0wQ/a.qR/}/bg/d.t/e/y0Q0V0e0g0i0t0x0yu.y.R.u.v.x/^/d/f/k0R0W0]0^0b0k0m0r0s0uX/_.o.y/x0hR/z/^V0j0^0k0sR/q.{QsOS$Os,dR,d*WQ&r$UR)_&rS%z#W$WS(p%z(sT(s%}&tQ%n#OQ%u#SW(b%n%u(g(kQ(g%rR(k%wQ&}$bR)e&}Q(v&OQ+_(qT+e(v+_Q(P%]R*w(PS(S%`%aY*{(S*|-Q.W/PU*|(T(U(VU-Q*}+O+PS.W-R-SR/P.XQ#_^R&R#_Q#b_R&T#bQ#e`R&X#eQ(y&US+j(y+kR+k(zQ+n({R-a+nQ#iaR&[#iQ#lbR&^#lQ#ocR&`#oQ#qdR&a#qQ#tgQ&c#rW&f#t&c)b+uQ)b&wR+u1OQ$_xS&y$_&zR&z$`Q'X$lR)q'XQ&k#yR)Z&kQ$h!QR'R$hQ+y)iS-f+y.cR.c-gQ'V$jR)n'VQ,R)tR-k,RQ#wkR&h#wQ)x']R,U)xQ'`$qS*P'`*QR*Q'aQ'h$xR*X'hQ'm$yS*c'm,nR,n*dQ,t*iR.O,tWoOs*W,dR#{oQ.Q,xR.m.Qd/e.t/y0Q0V0e0g0i0t0x0yR0P/eU/].o/x0hR/w/]Q0d0VS0p0d0qR0q0eS0_/y/zR0l0_Q/g.tR0S/gR!`PXrOs*W,dWqOs*W,dR'f$wYkOs$w*W,dR&g#v[xOs#v$w*W,dR&x$^&hQOYZ[isuw}!O!S!U!V!Z!n!p!t!u!v!x!y#c#g#j#m#s#v$Y$[$^$a$u$w%[%a%h%k%m%t%y%{&V&b&o&s'O'P'W'Z'b'i'l'}(O(R(T(U(Y(a(i(o(u(x)V)X)a)p)w)y*S*W*^*b*l*v*y*z*}+T+U+W+Y+]+^+a+h+i+l+t+w,O,d,l,m,p,z,{,|-O-P-S-U-W-Y-[-^-_-b-y-{.S.V.Y.}/O/s0[0z0{0|0}1P1Q1R1S1V1ZQ!sTQ#rfQ$PtU$by%p(eS$q!W$tQ$}!^Q%S!hQ%T!iQ%U!jQ%V!kQ%W!lQ%X!mQ%r#PQ%w#TQ%}#XQ&O#YQ&t$XQ'a$rQ'x%OQ)W&dU)c&|)d+vW)|'_*O,],^Q+R(_Q+[(nQ,[)}Q-Z+dQ0Y/oR1O1TQ#OYQ#SZQ$o!UQ$p!VQ%`!pQ(V%a^(^%m%t(a(i+T+W+Y^*x(R*z-O-P.V/O/sQ+O(TQ+P(UQ,X)yQ,}*yQ-R*}Q.T,{Q.U,|Q.X-SQ.|.SR/r.}[gOs#v$w*W,d!^!{YZ!U!V!p%a%m%t(R(T(U(a(i)y*y*z*}+T+W+Y,{,|-O-P-S.S.V.}/O/sQ#W[Q#uiS$Ww}Q$e!OW$l!S$a'b*SS$y!Z$uW%Y!n(O*v,zY&U#c#g#j#m+l`&e#s&b)V)X)a+t-b1SQ&u$YQ&v$[Q&w$^Q'{%[Q(]%kW(m%y(o+]+aQ(q%{Q(z&VQ)]&oS)`&s1QQ)f'OQ)g'PU)o'W)p,OQ)v'ZQ*]'iY*a'l*b,l,m-yQ*t'}S+Q(Y1RW+c(u+^-W-[W+g(x+i-^-_Q,T)wQ,i*^Q,v*lQ-]+hQ-c+wQ-z,pQ.]-YR.k-{hUOs#s#v$w&b&s(Y)V)X*W,d%Y!zYZ[iw}!O!S!U!V!Z!n!p#c#g#j#m$Y$[$^$a$u%[%a%k%m%t%y%{&V&o'O'P'W'Z'b'i'l'}(O(R(T(U(a(i(o(u(x)a)p)w)y*S*^*b*l*v*y*z*}+T+W+Y+]+^+a+h+i+l+t+w,O,l,m,p,z,{,|-O-P-S-W-Y-[-^-_-b-y-{.S.V.}/O/s1Q1R1SQ$QuW%e!t!x0{1VQ%f!uQ%g!vQ%i!yQ%s0zS(X%h1PQ(Z0|Q([0}Q-T+UQ.[-US/Q.Y0[R1X1ZU$Uv/S1YR)^&q[hOs#v$w*W,da!}Y#c#g#j#m$^$a+lQ#][Q$ZwR$d}Q%o#OQ%v#SQ%|#WQ'{%YQ(h%rQ(l%wQ(t%}Q(w&OQ+`(qQ,y*tQ.Z-TQ/U.[R/u/TQ$cyQ(d%pR+V(eQ/T.YR0f0[R#VZR#[[R%_!nQ%]!nV*u(O*v,z!]!qQ!s#r$P$b$q$}%S%T%U%V%W%X%r%w%}&O&t'a'x)W)c)|+R+[,[-Z0Y1OR%b!pQ&W#cQ&Z#gQ&]#jQ&_#mR-`+lQ(}&WQ)P&ZQ)R&]Q)T&_Q+p)OQ+q)QQ+r)SQ+s)UQ.^-`R/V._Q$m!SQ&{$aQ*R'bR,`*SQ#zmQ$f!PQ$i!QR'T$hQ)h'SR+|)kQ)h'SQ+{)jR+|)kR$k!RR)u'YXqOs*W,dQ$s!WR'c$tQ$z!ZR'd$uR*k'pQ*i'pV-|,s-}.lQ.{.RQ/i.uR/j.vU.t.R.u.vQ/n.xQ/y/^Q0O/dU0Q/f0R0bQ0V/kQ0e0WQ0g0]U0i0^0k0sQ0t0mQ0x0rR0y0uR/m.wR/{/^\",\n nodeNames: \"⚠ print { { { { Comment Script AssignStatement * BinaryExpression BitOp BitOp BitOp BitOp ArithOp ArithOp @ ArithOp ** UnaryExpression ArithOp BitOp AwaitExpression await ) ( ParenthesizedExpression BinaryExpression or and CompareOp in not is UnaryExpression ConditionalExpression if else LambdaExpression lambda ParamList VariableName AssignOp , : NamedExpression AssignOp YieldExpression yield from TupleExpression ComprehensionExpression async for LambdaExpression ] [ ArrayExpression ArrayComprehensionExpression } { DictionaryExpression DictionaryComprehensionExpression SetExpression SetComprehensionExpression CallExpression ArgList AssignOp MemberExpression . PropertyName Number String FormatString FormatReplacement FormatConversion FormatSpec FormatReplacement FormatReplacement FormatReplacement FormatReplacement ContinuedString Ellipsis None Boolean TypeDef AssignOp UpdateStatement UpdateOp ExpressionStatement DeleteStatement del PassStatement pass BreakStatement break ContinueStatement continue ReturnStatement return YieldStatement PrintStatement RaiseStatement raise ImportStatement import as ScopeStatement global nonlocal AssertStatement assert TypeDefinition type TypeParamList TypeParam StatementGroup ; IfStatement Body elif WhileStatement while ForStatement TryStatement try except finally WithStatement with FunctionDefinition def ParamList AssignOp TypeDef ClassDefinition class DecoratedStatement Decorator At MatchStatement match MatchBody MatchClause case CapturePattern LiteralPattern ArithOp ArithOp AsPattern OrPattern LogicOp AttributePattern SequencePattern MappingPattern StarPattern ClassPattern PatternArgList KeywordPattern KeywordPattern Guard\",\n maxTerm: 283,\n context: trackIndent,\n nodeProps: [\n [\"group\", -15,8,88,90,91,93,95,97,99,101,102,103,105,108,111,113,\"Statement Statement\",-22,10,20,23,27,42,51,52,58,59,62,63,64,65,66,69,72,73,74,82,83,84,85,\"Expression\",-10,117,119,122,124,125,129,131,136,138,141,\"Statement\",-9,146,147,150,151,153,154,155,156,157,\"Pattern\"],\n [\"openedBy\", 25,\"(\",56,\"[\",60,\"{\"],\n [\"closedBy\", 26,\")\",57,\"]\",61,\"}\"]\n ],\n propSources: [pythonHighlighting],\n skippedNodes: [0,6],\n repeatNodeCount: 38,\n tokenData: \"%-W#sR!`OX%TXY=|Y[%T[]=|]p%Tpq=|qr@_rsDOst!+|tu%Tuv!Nnvw#!|wx#$Wxy#:Uyz#;Yz{#<^{|#>x|}#@S}!O#AW!O!P#Ci!P!Q#N_!Q!R$!y!R![$&w![!]$1e!]!^$3s!^!_$4w!_!`$7c!`!a$8m!a!b%T!b!c$;U!c!d$W!e!h$W#V#Y$Q<%lO$Xc&r!b&jS&mW%p!TOX%TXY=|Y[%T[]=|]p%Tpq=|qr%Trs&Vsw%Twx/Xx#O%T#O#P?d#P#o%T#o#p8^#p#q%T#q#r8^#r;'S%T;'S;=`=v<%lO%T#s?i[&r!bOY%TYZ=|Z]%T]^=|^#o%T#o#p8^#p#q%T#q#r8^#r;'S%T;'S;=`=P;=`<%l8^<%lO%T!q@hd&r!b&jS&mWOr%Trs&Vsw%Twx/Xx!_%T!_!`Av!`#O%T#O#P7o#P#T%T#T#UBz#U#f%T#f#gBz#g#hBz#h#o%T#o#p8^#p#q%T#q#r8^#r;'S%T;'S;=`=v<%lO%T!qBR]oR&r!b&jS&mWOr%Trs&Vsw%Twx/Xx#O%T#O#P7o#P#o%T#o#p8^#p#q%T#q#r8^#r;'S%T;'S;=`=v<%lO%T!qCV]!nR&r!b&jS&mWOr%Trs&Vsw%Twx/Xx#O%T#O#P7o#P#o%T#o#p8^#p#q%T#q#r8^#r;'S%T;'S;=`=v<%lO%T#cDXa&r!b&jS&hsOYE^YZ%TZ]E^]^%T^rE^rs!)|swE^wxGpx#OE^#O#P!!u#P#oE^#o#p!#d#p#qE^#q#r!#d#r;'SE^;'S;=`!)v<%lOE^#cEia&r!b&jS&mW&hsOYE^YZ%TZ]E^]^%T^rE^rsFnswE^wxGpx#OE^#O#P!!u#P#oE^#o#p!#d#p#qE^#q#r!#d#r;'SE^;'S;=`!)v<%lOE^#cFw]&r!b&jS&hsOr%Trs'Vsw%Twx/Xx#O%T#O#P7o#P#o%T#o#p8^#p#q%T#q#r8^#r;'S%T;'S;=`=v<%lO%T#cGya&r!b&mW&hsOYE^YZ%TZ]E^]^%T^rE^rsFnswE^wxIOx#OE^#O#P!!u#P#oE^#o#p!#d#p#qE^#q#r!#d#r;'SE^;'S;=`!)v<%lOE^#cIXa&r!b&mW&hsOYE^YZ%TZ]E^]^%T^rE^rsFnswE^wxJ^x#OE^#O#P!!u#P#oE^#o#p!#d#p#qE^#q#r!#d#r;'SE^;'S;=`!)v<%lOE^#_Jg_&r!b&mW&hsOYJ^YZ1XZ]J^]^1X^rJ^rsKfs#OJ^#O#PL`#P#oJ^#o#pL}#p#qJ^#q#rL}#r;'SJ^;'S;=`!!o<%lOJ^#_KmZ&r!b&hsOr1Xrs2ys#O1X#O#P3q#P#o1X#o#p4`#p#q1X#q#r4`#r;'S1X;'S;=`7i<%lO1X#_LeW&r!bO#oJ^#o#pL}#p#qJ^#q#rL}#r;'SJ^;'S;=`! r;=`<%lL}<%lOJ^{MUZ&mW&hsOYL}YZ4`Z]L}]^4`^rL}rsMws#OL}#O#PNc#P;'SL};'S;=`! l<%lOL}{M|V&hsOr4`rs5ds#O4`#O#P5y#P;'S4`;'S;=`6t<%lO4`{NfRO;'SL};'S;=`No;=`OL}{Nv[&mW&hsOYL}YZ4`Z]L}]^4`^rL}rsMws#OL}#O#PNc#P;'SL};'S;=`! l;=`<%lL}<%lOL}{! oP;=`<%lL}#_! y[&mW&hsOYL}YZ4`Z]L}]^4`^rL}rsMws#OL}#O#PNc#P;'SL};'S;=`! l;=`<%lJ^<%lOL}#_!!rP;=`<%lJ^#c!!zW&r!bO#oE^#o#p!#d#p#qE^#q#r!#d#r;'SE^;'S;=`!(q;=`<%l!#d<%lOE^!P!#m]&jS&mW&hsOY!#dYZ8^Z]!#d]^8^^r!#drs!$fsw!#dwx!%Yx#O!#d#O#P!'Y#P;'S!#d;'S;=`!(k<%lO!#d!P!$mX&jS&hsOr8^rs9rsw8^wx:dx#O8^#O#P;v#P;'S8^;'S;=`^s#O!=U#O#P!@j#P#o!=U#o#p!Ag#p#q!=U#q#r!Ag#r;'S!=U;'S;=`!FQ<%lO!=U#o!>e_U!T&r!bOY!=UYZ1XZ]!=U]^1X^r!=Urs!?ds#O!=U#O#P!@j#P#o!=U#o#p!Ag#p#q!=U#q#r!Ag#r;'S!=U;'S;=`!FQ<%lO!=U#o!?k_U!T&r!bOY!=UYZ1XZ]!=U]^1X^r!=Urs!3`s#O!=U#O#P!@j#P#o!=U#o#p!Ag#p#q!=U#q#r!Ag#r;'S!=U;'S;=`!FQ<%lO!=U#o!@q[U!T&r!bOY!=UYZ1XZ]!=U]^1X^#o!=U#o#p!Ag#p#q!=U#q#r!Ag#r;'S!=U;'S;=`!Ec;=`<%l4`<%lO!=U!]!AnZU!T&mWOY!AgYZ4`Z]!Ag]^4`^r!Agrs!Bas#O!Ag#O#P!DP#P;'S!Ag;'S;=`!E]<%lO!Ag!]!BfZU!TOY!AgYZ4`Z]!Ag]^4`^r!Agrs!CXs#O!Ag#O#P!DP#P;'S!Ag;'S;=`!E]<%lO!Ag!]!C^ZU!TOY!AgYZ4`Z]!Ag]^4`^r!Agrs!4Ys#O!Ag#O#P!DP#P;'S!Ag;'S;=`!E]<%lO!Ag!]!DUWU!TOY!AgYZ4`Z]!Ag]^4`^;'S!Ag;'S;=`!Dn;=`<%l4`<%lO!Ag!]!DsW&mWOr4`rs4zs#O4`#O#P5y#P;'S4`;'S;=`6t;=`<%l!Ag<%lO4`!]!E`P;=`<%l!Ag#o!EhW&mWOr4`rs4zs#O4`#O#P5y#P;'S4`;'S;=`6t;=`<%l!=U<%lO4`#o!FTP;=`<%l!=U#s!F_[U!T&r!bOY!+|YZ%TZ]!+|]^%T^#o!+|#o#p!GT#p#q!+|#q#r!GT#r;'S!+|;'S;=`!Mq;=`<%l8^<%lO!+|!a!G^]U!T&jS&mWOY!GTYZ8^Z]!GT]^8^^r!GTrs!HVsw!GTwx!JVx#O!GT#O#P!LV#P;'S!GT;'S;=`!Mk<%lO!GT!a!H^]U!T&jSOY!GTYZ8^Z]!GT]^8^^r!GTrs!IVsw!GTwx!JVx#O!GT#O#P!LV#P;'S!GT;'S;=`!Mk<%lO!GT!a!I^]U!T&jSOY!GTYZ8^Z]!GT]^8^^r!GTrs!5wsw!GTwx!JVx#O!GT#O#P!LV#P;'S!GT;'S;=`!Mk<%lO!GT!a!J^]U!T&mWOY!GTYZ8^Z]!GT]^8^^r!GTrs!HVsw!GTwx!KVx#O!GT#O#P!LV#P;'S!GT;'S;=`!Mk<%lO!GT!a!K^]U!T&mWOY!GTYZ8^Z]!GT]^8^^r!GTrs!HVsw!GTwx!Agx#O!GT#O#P!LV#P;'S!GT;'S;=`!Mk<%lO!GT!a!L[WU!TOY!GTYZ8^Z]!GT]^8^^;'S!GT;'S;=`!Lt;=`<%l8^<%lO!GT!a!L{Y&jS&mWOr8^rs9Qsw8^wx:dx#O8^#O#P;v#P;'S8^;'S;=`Q<%lO$TP;=`<%l$ei&r!b&jS&mW&g`&SsOr%Trs$@Ssw%Twx$C`x!Q%T!Q![$Q<%lO$Q<%lO$Q<%lO$Q<%lO$Q<%lO$ spec_identifier[value] || -1}],\n tokenPrec: 7372\n});\n\nexport { parser };\n","import { parser } from '@lezer/python';\nimport { syntaxTree, LRLanguage, indentNodeProp, delimitedIndent, foldNodeProp, foldInside, LanguageSupport } from '@codemirror/language';\nimport { NodeWeakMap, IterMode } from '@lezer/common';\nimport { snippetCompletion, ifNotIn, completeFromList } from '@codemirror/autocomplete';\n\nconst cache = /*@__PURE__*/new NodeWeakMap();\nconst ScopeNodes = /*@__PURE__*/new Set([\n \"Script\", \"Body\",\n \"FunctionDefinition\", \"ClassDefinition\", \"LambdaExpression\",\n \"ForStatement\", \"MatchClause\"\n]);\nfunction defID(type) {\n return (node, def, outer) => {\n if (outer)\n return false;\n let id = node.node.getChild(\"VariableName\");\n if (id)\n def(id, type);\n return true;\n };\n}\nconst gatherCompletions = {\n FunctionDefinition: /*@__PURE__*/defID(\"function\"),\n ClassDefinition: /*@__PURE__*/defID(\"class\"),\n ForStatement(node, def, outer) {\n if (outer)\n for (let child = node.node.firstChild; child; child = child.nextSibling) {\n if (child.name == \"VariableName\")\n def(child, \"variable\");\n else if (child.name == \"in\")\n break;\n }\n },\n ImportStatement(_node, def) {\n var _a, _b;\n let { node } = _node;\n let isFrom = ((_a = node.firstChild) === null || _a === void 0 ? void 0 : _a.name) == \"from\";\n for (let ch = node.getChild(\"import\"); ch; ch = ch.nextSibling) {\n if (ch.name == \"VariableName\" && ((_b = ch.nextSibling) === null || _b === void 0 ? void 0 : _b.name) != \"as\")\n def(ch, isFrom ? \"variable\" : \"namespace\");\n }\n },\n AssignStatement(node, def) {\n for (let child = node.node.firstChild; child; child = child.nextSibling) {\n if (child.name == \"VariableName\")\n def(child, \"variable\");\n else if (child.name == \":\" || child.name == \"AssignOp\")\n break;\n }\n },\n ParamList(node, def) {\n for (let prev = null, child = node.node.firstChild; child; child = child.nextSibling) {\n if (child.name == \"VariableName\" && (!prev || !/\\*|AssignOp/.test(prev.name)))\n def(child, \"variable\");\n prev = child;\n }\n },\n CapturePattern: /*@__PURE__*/defID(\"variable\"),\n AsPattern: /*@__PURE__*/defID(\"variable\"),\n __proto__: null\n};\nfunction getScope(doc, node) {\n let cached = cache.get(node);\n if (cached)\n return cached;\n let completions = [], top = true;\n function def(node, type) {\n let name = doc.sliceString(node.from, node.to);\n completions.push({ label: name, type });\n }\n node.cursor(IterMode.IncludeAnonymous).iterate(node => {\n if (node.name) {\n let gather = gatherCompletions[node.name];\n if (gather && gather(node, def, top) || !top && ScopeNodes.has(node.name))\n return false;\n top = false;\n }\n else if (node.to - node.from > 8192) {\n // Allow caching for bigger internal nodes\n for (let c of getScope(doc, node.node))\n completions.push(c);\n return false;\n }\n });\n cache.set(node, completions);\n return completions;\n}\nconst Identifier = /^[\\w\\xa1-\\uffff][\\w\\d\\xa1-\\uffff]*$/;\nconst dontComplete = [\"String\", \"FormatString\", \"Comment\", \"PropertyName\"];\n/**\nCompletion source that looks up locally defined names in\nPython code.\n*/\nfunction localCompletionSource(context) {\n let inner = syntaxTree(context.state).resolveInner(context.pos, -1);\n if (dontComplete.indexOf(inner.name) > -1)\n return null;\n let isWord = inner.name == \"VariableName\" ||\n inner.to - inner.from < 20 && Identifier.test(context.state.sliceDoc(inner.from, inner.to));\n if (!isWord && !context.explicit)\n return null;\n let options = [];\n for (let pos = inner; pos; pos = pos.parent) {\n if (ScopeNodes.has(pos.name))\n options = options.concat(getScope(context.state.doc, pos));\n }\n return {\n options,\n from: isWord ? inner.from : context.pos,\n validFor: Identifier\n };\n}\nconst globals = /*@__PURE__*/[\n \"__annotations__\", \"__builtins__\", \"__debug__\", \"__doc__\", \"__import__\", \"__name__\",\n \"__loader__\", \"__package__\", \"__spec__\",\n \"False\", \"None\", \"True\"\n].map(n => ({ label: n, type: \"constant\" })).concat(/*@__PURE__*/[\n \"ArithmeticError\", \"AssertionError\", \"AttributeError\", \"BaseException\", \"BlockingIOError\",\n \"BrokenPipeError\", \"BufferError\", \"BytesWarning\", \"ChildProcessError\", \"ConnectionAbortedError\",\n \"ConnectionError\", \"ConnectionRefusedError\", \"ConnectionResetError\", \"DeprecationWarning\",\n \"EOFError\", \"Ellipsis\", \"EncodingWarning\", \"EnvironmentError\", \"Exception\", \"FileExistsError\",\n \"FileNotFoundError\", \"FloatingPointError\", \"FutureWarning\", \"GeneratorExit\", \"IOError\",\n \"ImportError\", \"ImportWarning\", \"IndentationError\", \"IndexError\", \"InterruptedError\",\n \"IsADirectoryError\", \"KeyError\", \"KeyboardInterrupt\", \"LookupError\", \"MemoryError\",\n \"ModuleNotFoundError\", \"NameError\", \"NotADirectoryError\", \"NotImplemented\", \"NotImplementedError\",\n \"OSError\", \"OverflowError\", \"PendingDeprecationWarning\", \"PermissionError\", \"ProcessLookupError\",\n \"RecursionError\", \"ReferenceError\", \"ResourceWarning\", \"RuntimeError\", \"RuntimeWarning\",\n \"StopAsyncIteration\", \"StopIteration\", \"SyntaxError\", \"SyntaxWarning\", \"SystemError\",\n \"SystemExit\", \"TabError\", \"TimeoutError\", \"TypeError\", \"UnboundLocalError\", \"UnicodeDecodeError\",\n \"UnicodeEncodeError\", \"UnicodeError\", \"UnicodeTranslateError\", \"UnicodeWarning\", \"UserWarning\",\n \"ValueError\", \"Warning\", \"ZeroDivisionError\"\n].map(n => ({ label: n, type: \"type\" }))).concat(/*@__PURE__*/[\n \"bool\", \"bytearray\", \"bytes\", \"classmethod\", \"complex\", \"float\", \"frozenset\", \"int\", \"list\",\n \"map\", \"memoryview\", \"object\", \"range\", \"set\", \"staticmethod\", \"str\", \"super\", \"tuple\", \"type\"\n].map(n => ({ label: n, type: \"class\" }))).concat(/*@__PURE__*/[\n \"abs\", \"aiter\", \"all\", \"anext\", \"any\", \"ascii\", \"bin\", \"breakpoint\", \"callable\", \"chr\",\n \"compile\", \"delattr\", \"dict\", \"dir\", \"divmod\", \"enumerate\", \"eval\", \"exec\", \"exit\", \"filter\",\n \"format\", \"getattr\", \"globals\", \"hasattr\", \"hash\", \"help\", \"hex\", \"id\", \"input\", \"isinstance\",\n \"issubclass\", \"iter\", \"len\", \"license\", \"locals\", \"max\", \"min\", \"next\", \"oct\", \"open\",\n \"ord\", \"pow\", \"print\", \"property\", \"quit\", \"repr\", \"reversed\", \"round\", \"setattr\", \"slice\",\n \"sorted\", \"sum\", \"vars\", \"zip\"\n].map(n => ({ label: n, type: \"function\" })));\nconst snippets = [\n /*@__PURE__*/snippetCompletion(\"def ${name}(${params}):\\n\\t${}\", {\n label: \"def\",\n detail: \"function\",\n type: \"keyword\"\n }),\n /*@__PURE__*/snippetCompletion(\"for ${name} in ${collection}:\\n\\t${}\", {\n label: \"for\",\n detail: \"loop\",\n type: \"keyword\"\n }),\n /*@__PURE__*/snippetCompletion(\"while ${}:\\n\\t${}\", {\n label: \"while\",\n detail: \"loop\",\n type: \"keyword\"\n }),\n /*@__PURE__*/snippetCompletion(\"try:\\n\\t${}\\nexcept ${error}:\\n\\t${}\", {\n label: \"try\",\n detail: \"/ except block\",\n type: \"keyword\"\n }),\n /*@__PURE__*/snippetCompletion(\"if ${}:\\n\\t\\n\", {\n label: \"if\",\n detail: \"block\",\n type: \"keyword\"\n }),\n /*@__PURE__*/snippetCompletion(\"if ${}:\\n\\t${}\\nelse:\\n\\t${}\", {\n label: \"if\",\n detail: \"/ else block\",\n type: \"keyword\"\n }),\n /*@__PURE__*/snippetCompletion(\"class ${name}:\\n\\tdef __init__(self, ${params}):\\n\\t\\t\\t${}\", {\n label: \"class\",\n detail: \"definition\",\n type: \"keyword\"\n }),\n /*@__PURE__*/snippetCompletion(\"import ${module}\", {\n label: \"import\",\n detail: \"statement\",\n type: \"keyword\"\n }),\n /*@__PURE__*/snippetCompletion(\"from ${module} import ${names}\", {\n label: \"from\",\n detail: \"import\",\n type: \"keyword\"\n })\n];\n/**\nAutocompletion for built-in Python globals and keywords.\n*/\nconst globalCompletion = /*@__PURE__*/ifNotIn(dontComplete, /*@__PURE__*/completeFromList(/*@__PURE__*/globals.concat(snippets)));\n\nfunction indentBody(context, node) {\n let base = context.baseIndentFor(node);\n let line = context.lineAt(context.pos, -1), to = line.from + line.text.length;\n // Don't consider blank, deindented lines at the end of the\n // block part of the block\n if (/^\\s*($|#)/.test(line.text) &&\n context.node.to < to + 100 &&\n !/\\S/.test(context.state.sliceDoc(to, context.node.to)) &&\n context.lineIndent(context.pos, -1) <= base)\n return null;\n // A normally deindenting keyword that appears at a higher\n // indentation than the block should probably be handled by the next\n // level\n if (/^\\s*(else:|elif |except |finally:)/.test(context.textAfter) && context.lineIndent(context.pos, -1) > base)\n return null;\n return base + context.unit;\n}\n/**\nA language provider based on the [Lezer Python\nparser](https://github.com/lezer-parser/python), extended with\nhighlighting and indentation information.\n*/\nconst pythonLanguage = /*@__PURE__*/LRLanguage.define({\n name: \"python\",\n parser: /*@__PURE__*/parser.configure({\n props: [\n /*@__PURE__*/indentNodeProp.add({\n Body: context => { var _a; return (_a = indentBody(context, context.node)) !== null && _a !== void 0 ? _a : context.continue(); },\n IfStatement: cx => /^\\s*(else:|elif )/.test(cx.textAfter) ? cx.baseIndent : cx.continue(),\n TryStatement: cx => /^\\s*(except |finally:|else:)/.test(cx.textAfter) ? cx.baseIndent : cx.continue(),\n \"TupleExpression ComprehensionExpression ParamList ArgList ParenthesizedExpression\": /*@__PURE__*/delimitedIndent({ closing: \")\" }),\n \"DictionaryExpression DictionaryComprehensionExpression SetExpression SetComprehensionExpression\": /*@__PURE__*/delimitedIndent({ closing: \"}\" }),\n \"ArrayExpression ArrayComprehensionExpression\": /*@__PURE__*/delimitedIndent({ closing: \"]\" }),\n \"String FormatString\": () => null,\n Script: context => {\n if (context.pos + /\\s*/.exec(context.textAfter)[0].length >= context.node.to) {\n let endBody = null;\n for (let cur = context.node, to = cur.to;;) {\n cur = cur.lastChild;\n if (!cur || cur.to != to)\n break;\n if (cur.type.name == \"Body\")\n endBody = cur;\n }\n if (endBody) {\n let bodyIndent = indentBody(context, endBody);\n if (bodyIndent != null)\n return bodyIndent;\n }\n }\n return context.continue();\n }\n }),\n /*@__PURE__*/foldNodeProp.add({\n \"ArrayExpression DictionaryExpression SetExpression TupleExpression\": foldInside,\n Body: (node, state) => ({ from: node.from + 1, to: node.to - (node.to == state.doc.length ? 0 : 1) })\n })\n ],\n }),\n languageData: {\n closeBrackets: {\n brackets: [\"(\", \"[\", \"{\", \"'\", '\"', \"'''\", '\"\"\"'],\n stringPrefixes: [\"f\", \"fr\", \"rf\", \"r\", \"u\", \"b\", \"br\", \"rb\",\n \"F\", \"FR\", \"RF\", \"R\", \"U\", \"B\", \"BR\", \"RB\"]\n },\n commentTokens: { line: \"#\" },\n indentOnInput: /^\\s*([\\}\\]\\)]|else:|elif |except |finally:)$/\n }\n});\n/**\nPython language support.\n*/\nfunction python() {\n return new LanguageSupport(pythonLanguage, [\n pythonLanguage.data.of({ autocomplete: localCompletionSource }),\n pythonLanguage.data.of({ autocomplete: globalCompletion }),\n ]);\n}\n\nexport { globalCompletion, localCompletionSource, python, pythonLanguage };\n"],"names":["newline","carriageReturn","braceOpen","backslash","bracketed","Set","isLineBreak","ch","newlines","input","stack","prev","next","acceptToken","context","depth","peek","canShift","spaces","advance","contextual","indentation","cDepth","chars","IndentLevel","parent","this","hash","topIndent","trackIndent","start","reduce","term","has","shift","space","i","length","charCodeAt","countIndent","read","pos","legacyPrint","test","String","fromCharCode","off","formatString","quote","len","content","brace","end","formatString1","formatString2","formatString1l","formatString2l","pythonHighlighting","import","Boolean","None","VariableName","PropertyName","Comment","Number","FormatString","UpdateOp","BitOp","CompareOp","AssignOp","Ellipsis","At","spec_identifier","__proto__","await","or","and","in","not","is","if","else","lambda","yield","from","async","for","True","False","del","pass","break","continue","return","raise","as","global","nonlocal","assert","type","elif","while","try","except","finally","with","def","class","match","case","parser","version","states","stateData","goto","nodeNames","maxTerm","nodeProps","propSources","skippedNodes","repeatNodeCount","tokenData","tokenizers","topRules","specialized","get","value","tokenPrec","cache","ScopeNodes","defID","node","outer","id","getChild","gatherCompletions","FunctionDefinition","ClassDefinition","ForStatement","child","firstChild","nextSibling","name","ImportStatement","_node","_a","_b","isFrom","AssignStatement","ParamList","CapturePattern","AsPattern","getScope","doc","cached","completions","top","sliceString","to","push","label","cursor","iterate","gather","c","set","Identifier","dontComplete","localCompletionSource","inner","state","resolveInner","indexOf","isWord","sliceDoc","explicit","options","concat","validFor","globals","map","n","snippets","detail","globalCompletion","indentBody","base","baseIndentFor","line","lineAt","text","lineIndent","textAfter","unit","pythonLanguage","configure","props","Body","IfStatement","cx","baseIndent","TryStatement","closing","Script","exec","endBody","cur","lastChild","bodyIndent","languageData","closeBrackets","brackets","stringPrefixes","commentTokens","indentOnInput","python","data","of","autocomplete"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/2411.index.js b/book/_build/html/_static/2411.index.js
new file mode 100644
index 0000000..76390a7
--- /dev/null
+++ b/book/_build/html/_static/2411.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[2411],{32411:(t,e,n)=>{function r(t){function e(t,e){t.cmdState.push(e)}function n(t){return t.cmdState.length>0?t.cmdState[t.cmdState.length-1]:null}function r(t,e,n){return function(){this.name=t,this.bracketNo=0,this.style=e,this.styles=n,this.argument=null,this.styleIdentifier=function(){return this.styles[this.bracketNo-1]||null},this.openBracket=function(){return this.bracketNo++,"bracket"},this.closeBracket=function(){}}}var a={};function i(t,e){t.f=e}function c(t,r){var c;if(t.match(/^\\[a-zA-Z@\xc0-\u1fff\u2060-\uffff]+/)){var f=t.current().slice(1);return e(r,c=new(c=a.hasOwnProperty(f)?a[f]:a.DEFAULT)),i(r,o),c.style}if(t.match(/^\\[$&%#{}_]/))return"tag";if(t.match(/^\\[,;!\/\\]/))return"tag";if(t.match("\\["))return i(r,(function(t,e){return u(t,e,"\\]")})),"keyword";if(t.match("\\("))return i(r,(function(t,e){return u(t,e,"\\)")})),"keyword";if(t.match("$$"))return i(r,(function(t,e){return u(t,e,"$$")})),"keyword";if(t.match("$"))return i(r,(function(t,e){return u(t,e,"$")})),"keyword";var m=t.next();return"%"==m?(t.skipToEnd(),"comment"):"}"==m||"]"==m?(c=n(r))?(c.closeBracket(m),i(r,o),"bracket"):"error":"{"==m||"["==m?(e(r,c=new(c=a.DEFAULT)),"bracket"):/\d/.test(m)?(t.eatWhile(/[\w.%]/),"atom"):(t.eatWhile(/[\w\-_]/),c=function(t){for(var e=t.cmdState,n=e.length-1;n>=0;n--){var r=e[n];if("DEFAULT"!=r.name)return r}return{styleIdentifier:function(){return null}}}(r),"begin"==c.name&&(c.argument=t.current()),c.styleIdentifier())}function u(t,e,n){if(t.eatSpace())return null;if(n&&t.match(n))return i(e,c),"keyword";if(t.match(/^\\[a-zA-Z@]+/))return"tag";if(t.match(/^[a-zA-Z]+/))return"variableName.special";if(t.match(/^\\[$&%#{}_]/))return"tag";if(t.match(/^\\[,;!\/]/))return"tag";if(t.match(/^[\^_&]/))return"tag";if(t.match(/^[+\-<>|=,\/@!*:;'"`~#?]/))return null;if(t.match(/^(\d+\.\d*|\d*\.\d+|\d+)/))return"number";var r=t.next();return"{"==r||"}"==r||"["==r||"]"==r||"("==r||")"==r?"bracket":"%"==r?(t.skipToEnd(),"comment"):"error"}function o(t,e){var r=t.peek();return"{"==r||"["==r?(n(e).openBracket(r),t.eat(r),i(e,c),"bracket"):/[ \t\r]/.test(r)?(t.eat(r),null):(i(e,c),function(t){var e=t.cmdState.pop();e&&e.closeBracket()}(e),c(t,e))}return a.importmodule=r("importmodule","tag",["string","builtin"]),a.documentclass=r("documentclass","tag",["","atom"]),a.usepackage=r("usepackage","tag",["atom"]),a.begin=r("begin","tag",["atom"]),a.end=r("end","tag",["atom"]),a.label=r("label","tag",["atom"]),a.ref=r("ref","tag",["atom"]),a.eqref=r("eqref","tag",["atom"]),a.cite=r("cite","tag",["atom"]),a.bibitem=r("bibitem","tag",["atom"]),a.Bibitem=r("Bibitem","tag",["atom"]),a.RBibitem=r("RBibitem","tag",["atom"]),a.DEFAULT=function(){this.name="DEFAULT",this.style="tag",this.styleIdentifier=this.openBracket=this.closeBracket=function(){}},{name:"stex",startState:function(){return{cmdState:[],f:t?function(t,e){return u(t,e)}:c}},copyState:function(t){return{cmdState:t.cmdState.slice(),f:t.f}},token:function(t,e){return e.f(t,e)},blankLine:function(t){t.f=c,t.cmdState.length=0},languageData:{commentTokens:{line:"%"}}}}n.r(e),n.d(e,{stex:()=>a,stexMath:()=>i});const a=r(!1),i=r(!0)}}]);
+//# sourceMappingURL=2411.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/2411.index.js.map b/book/_build/html/_static/2411.index.js.map
new file mode 100644
index 0000000..22f22d1
--- /dev/null
+++ b/book/_build/html/_static/2411.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"2411.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/stex.js"],"sourcesContent":["function mkStex(mathMode) {\n function pushCommand(state, command) {\n state.cmdState.push(command);\n }\n\n function peekCommand(state) {\n if (state.cmdState.length > 0) {\n return state.cmdState[state.cmdState.length - 1];\n } else {\n return null;\n }\n }\n\n function popCommand(state) {\n var plug = state.cmdState.pop();\n if (plug) {\n plug.closeBracket();\n }\n }\n\n // returns the non-default plugin closest to the end of the list\n function getMostPowerful(state) {\n var context = state.cmdState;\n for (var i = context.length - 1; i >= 0; i--) {\n var plug = context[i];\n if (plug.name == \"DEFAULT\") {\n continue;\n }\n return plug;\n }\n return { styleIdentifier: function() { return null; } };\n }\n\n function addPluginPattern(pluginName, cmdStyle, styles) {\n return function () {\n this.name = pluginName;\n this.bracketNo = 0;\n this.style = cmdStyle;\n this.styles = styles;\n this.argument = null; // \\begin and \\end have arguments that follow. These are stored in the plugin\n\n this.styleIdentifier = function() {\n return this.styles[this.bracketNo - 1] || null;\n };\n this.openBracket = function() {\n this.bracketNo++;\n return \"bracket\";\n };\n this.closeBracket = function() {};\n };\n }\n\n var plugins = {};\n\n plugins[\"importmodule\"] = addPluginPattern(\"importmodule\", \"tag\", [\"string\", \"builtin\"]);\n plugins[\"documentclass\"] = addPluginPattern(\"documentclass\", \"tag\", [\"\", \"atom\"]);\n plugins[\"usepackage\"] = addPluginPattern(\"usepackage\", \"tag\", [\"atom\"]);\n plugins[\"begin\"] = addPluginPattern(\"begin\", \"tag\", [\"atom\"]);\n plugins[\"end\"] = addPluginPattern(\"end\", \"tag\", [\"atom\"]);\n\n plugins[\"label\" ] = addPluginPattern(\"label\" , \"tag\", [\"atom\"]);\n plugins[\"ref\" ] = addPluginPattern(\"ref\" , \"tag\", [\"atom\"]);\n plugins[\"eqref\" ] = addPluginPattern(\"eqref\" , \"tag\", [\"atom\"]);\n plugins[\"cite\" ] = addPluginPattern(\"cite\" , \"tag\", [\"atom\"]);\n plugins[\"bibitem\" ] = addPluginPattern(\"bibitem\" , \"tag\", [\"atom\"]);\n plugins[\"Bibitem\" ] = addPluginPattern(\"Bibitem\" , \"tag\", [\"atom\"]);\n plugins[\"RBibitem\" ] = addPluginPattern(\"RBibitem\" , \"tag\", [\"atom\"]);\n\n plugins[\"DEFAULT\"] = function () {\n this.name = \"DEFAULT\";\n this.style = \"tag\";\n\n this.styleIdentifier = this.openBracket = this.closeBracket = function() {};\n };\n\n function setState(state, f) {\n state.f = f;\n }\n\n // called when in a normal (no environment) context\n function normal(source, state) {\n var plug;\n // Do we look like '\\command' ? If so, attempt to apply the plugin 'command'\n if (source.match(/^\\\\[a-zA-Z@\\xc0-\\u1fff\\u2060-\\uffff]+/)) {\n var cmdName = source.current().slice(1);\n plug = plugins.hasOwnProperty(cmdName) ? plugins[cmdName] : plugins[\"DEFAULT\"];\n plug = new plug();\n pushCommand(state, plug);\n setState(state, beginParams);\n return plug.style;\n }\n\n // escape characters\n if (source.match(/^\\\\[$&%#{}_]/)) {\n return \"tag\";\n }\n\n // white space control characters\n if (source.match(/^\\\\[,;!\\/\\\\]/)) {\n return \"tag\";\n }\n\n // find if we're starting various math modes\n if (source.match(\"\\\\[\")) {\n setState(state, function(source, state){ return inMathMode(source, state, \"\\\\]\"); });\n return \"keyword\";\n }\n if (source.match(\"\\\\(\")) {\n setState(state, function(source, state){ return inMathMode(source, state, \"\\\\)\"); });\n return \"keyword\";\n }\n if (source.match(\"$$\")) {\n setState(state, function(source, state){ return inMathMode(source, state, \"$$\"); });\n return \"keyword\";\n }\n if (source.match(\"$\")) {\n setState(state, function(source, state){ return inMathMode(source, state, \"$\"); });\n return \"keyword\";\n }\n\n var ch = source.next();\n if (ch == \"%\") {\n source.skipToEnd();\n return \"comment\";\n } else if (ch == '}' || ch == ']') {\n plug = peekCommand(state);\n if (plug) {\n plug.closeBracket(ch);\n setState(state, beginParams);\n } else {\n return \"error\";\n }\n return \"bracket\";\n } else if (ch == '{' || ch == '[') {\n plug = plugins[\"DEFAULT\"];\n plug = new plug();\n pushCommand(state, plug);\n return \"bracket\";\n } else if (/\\d/.test(ch)) {\n source.eatWhile(/[\\w.%]/);\n return \"atom\";\n } else {\n source.eatWhile(/[\\w\\-_]/);\n plug = getMostPowerful(state);\n if (plug.name == 'begin') {\n plug.argument = source.current();\n }\n return plug.styleIdentifier();\n }\n }\n\n function inMathMode(source, state, endModeSeq) {\n if (source.eatSpace()) {\n return null;\n }\n if (endModeSeq && source.match(endModeSeq)) {\n setState(state, normal);\n return \"keyword\";\n }\n if (source.match(/^\\\\[a-zA-Z@]+/)) {\n return \"tag\";\n }\n if (source.match(/^[a-zA-Z]+/)) {\n return \"variableName.special\";\n }\n // escape characters\n if (source.match(/^\\\\[$&%#{}_]/)) {\n return \"tag\";\n }\n // white space control characters\n if (source.match(/^\\\\[,;!\\/]/)) {\n return \"tag\";\n }\n // special math-mode characters\n if (source.match(/^[\\^_&]/)) {\n return \"tag\";\n }\n // non-special characters\n if (source.match(/^[+\\-<>|=,\\/@!*:;'\"`~#?]/)) {\n return null;\n }\n if (source.match(/^(\\d+\\.\\d*|\\d*\\.\\d+|\\d+)/)) {\n return \"number\";\n }\n var ch = source.next();\n if (ch == \"{\" || ch == \"}\" || ch == \"[\" || ch == \"]\" || ch == \"(\" || ch == \")\") {\n return \"bracket\";\n }\n\n if (ch == \"%\") {\n source.skipToEnd();\n return \"comment\";\n }\n return \"error\";\n }\n\n function beginParams(source, state) {\n var ch = source.peek(), lastPlug;\n if (ch == '{' || ch == '[') {\n lastPlug = peekCommand(state);\n lastPlug.openBracket(ch);\n source.eat(ch);\n setState(state, normal);\n return \"bracket\";\n }\n if (/[ \\t\\r]/.test(ch)) {\n source.eat(ch);\n return null;\n }\n setState(state, normal);\n popCommand(state);\n\n return normal(source, state);\n }\n\n return {\n name: \"stex\",\n startState: function() {\n var f = mathMode ? function(source, state){ return inMathMode(source, state); } : normal;\n return {\n cmdState: [],\n f: f\n };\n },\n copyState: function(s) {\n return {\n cmdState: s.cmdState.slice(),\n f: s.f\n };\n },\n token: function(stream, state) {\n return state.f(stream, state);\n },\n blankLine: function(state) {\n state.f = normal;\n state.cmdState.length = 0;\n },\n languageData: {\n commentTokens: {line: \"%\"}\n }\n };\n};\n\nexport const stex = mkStex(false)\nexport const stexMath = mkStex(true)\n"],"names":["mkStex","mathMode","pushCommand","state","command","cmdState","push","peekCommand","length","addPluginPattern","pluginName","cmdStyle","styles","this","name","bracketNo","style","argument","styleIdentifier","openBracket","closeBracket","plugins","setState","f","normal","source","plug","match","cmdName","current","slice","hasOwnProperty","beginParams","inMathMode","ch","next","skipToEnd","test","eatWhile","context","i","getMostPowerful","endModeSeq","eatSpace","peek","eat","pop","popCommand","startState","copyState","s","token","stream","blankLine","languageData","commentTokens","line","stex","stexMath"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/2444.index.js b/book/_build/html/_static/2444.index.js
new file mode 100644
index 0000000..50935fa
--- /dev/null
+++ b/book/_build/html/_static/2444.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[2444],{12444:(e,t,n)=>{n.r(t),n.d(t,{cypher:()=>h});var r,a=function(e){return new RegExp("^(?:"+e.join("|")+")$","i")},o=function(e){r=null;var t=e.next();if('"'===t)return e.match(/^.*?"/),"string";if("'"===t)return e.match(/^.*?'/),"string";if(/[{}\(\),\.;\[\]]/.test(t))return r=t,"punctuation";if("/"===t&&e.eat("/"))return e.skipToEnd(),"comment";if(u.test(t))return e.eatWhile(u),null;if(e.eatWhile(/[_\w\d]/),e.eat(":"))return e.eatWhile(/[\w\d_\-]/),"atom";var n=e.current();return l.test(n)?"builtin":c.test(n)?"def":d.test(n)||p.test(n)?"keyword":"variable"},s=function(e,t,n){return e.context={prev:e.context,indent:e.indent,col:n,type:t}},i=function(e){return e.indent=e.context.indent,e.context=e.context.prev},l=a(["abs","acos","allShortestPaths","asin","atan","atan2","avg","ceil","coalesce","collect","cos","cot","count","degrees","e","endnode","exp","extract","filter","floor","haversin","head","id","keys","labels","last","left","length","log","log10","lower","ltrim","max","min","node","nodes","percentileCont","percentileDisc","pi","radians","rand","range","reduce","rel","relationship","relationships","replace","reverse","right","round","rtrim","shortestPath","sign","sin","size","split","sqrt","startnode","stdev","stdevp","str","substring","sum","tail","tan","timestamp","toFloat","toInt","toString","trim","type","upper"]),c=a(["all","and","any","contains","exists","has","in","none","not","or","single","xor"]),d=a(["as","asc","ascending","assert","by","case","commit","constraint","create","csv","cypher","delete","desc","descending","detach","distinct","drop","else","end","ends","explain","false","fieldterminator","foreach","from","headers","in","index","is","join","limit","load","match","merge","null","on","optional","order","periodic","profile","remove","return","scan","set","skip","start","starts","then","true","union","unique","unwind","using","when","where","with","call","yield"]),p=a(["access","active","assign","all","alter","as","catalog","change","copy","create","constraint","constraints","current","database","databases","dbms","default","deny","drop","element","elements","exists","from","grant","graph","graphs","if","index","indexes","label","labels","management","match","name","names","new","node","nodes","not","of","on","or","password","populated","privileges","property","read","relationship","relationships","remove","replace","required","revoke","role","roles","set","show","start","status","stop","suspended","to","traverse","type","types","user","users","with","write"]),u=/[*+\-<>=&|~%^]/;const h={name:"cypher",startState:function(){return{tokenize:o,context:null,indent:0,col:0}},token:function(e,t){if(e.sol()&&(t.context&&null==t.context.align&&(t.context.align=!1),t.indent=e.indentation()),e.eatSpace())return null;var n=t.tokenize(e,t);if("comment"!==n&&t.context&&null==t.context.align&&"pattern"!==t.context.type&&(t.context.align=!0),"("===r)s(t,")",e.column());else if("["===r)s(t,"]",e.column());else if("{"===r)s(t,"}",e.column());else if(/[\]\}\)]/.test(r)){for(;t.context&&"pattern"===t.context.type;)i(t);t.context&&r===t.context.type&&i(t)}else"."===r&&t.context&&"pattern"===t.context.type?i(t):/atom|string|variable/.test(n)&&t.context&&(/[\}\]]/.test(t.context.type)?s(t,"pattern",e.column()):"pattern"!==t.context.type||t.context.align||(t.context.align=!0,t.context.col=e.column()));return n},indent:function(e,t,n){var r=t&&t.charAt(0),a=e.context;if(/[\]\}]/.test(r))for(;a&&"pattern"===a.type;)a=a.prev;var o=a&&r===a.type;return a?"keywords"===a.type?null:a.align?a.col+(o?0:1):a.indent+(o?0:n.unit):0}}}}]);
+//# sourceMappingURL=2444.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/2444.index.js.map b/book/_build/html/_static/2444.index.js.map
new file mode 100644
index 0000000..1e5f25b
--- /dev/null
+++ b/book/_build/html/_static/2444.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"2444.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/cypher.js"],"sourcesContent":["var wordRegexp = function(words) {\n return new RegExp(\"^(?:\" + words.join(\"|\") + \")$\", \"i\");\n};\n\nvar tokenBase = function(stream/*, state*/) {\n curPunc = null;\n var ch = stream.next();\n if (ch ==='\"') {\n stream.match(/^.*?\"/);\n return \"string\";\n }\n if (ch === \"'\") {\n stream.match(/^.*?'/);\n return \"string\";\n }\n if (/[{}\\(\\),\\.;\\[\\]]/.test(ch)) {\n curPunc = ch;\n return \"punctuation\";\n } else if (ch === \"/\" && stream.eat(\"/\")) {\n stream.skipToEnd();\n return \"comment\";\n } else if (operatorChars.test(ch)) {\n stream.eatWhile(operatorChars);\n return null;\n } else {\n stream.eatWhile(/[_\\w\\d]/);\n if (stream.eat(\":\")) {\n stream.eatWhile(/[\\w\\d_\\-]/);\n return \"atom\";\n }\n var word = stream.current();\n if (funcs.test(word)) return \"builtin\";\n if (preds.test(word)) return \"def\";\n if (keywords.test(word) || systemKeywords.test(word)) return \"keyword\";\n return \"variable\";\n }\n};\nvar pushContext = function(state, type, col) {\n return state.context = {\n prev: state.context,\n indent: state.indent,\n col: col,\n type: type\n };\n};\nvar popContext = function(state) {\n state.indent = state.context.indent;\n return state.context = state.context.prev;\n};\nvar curPunc;\nvar funcs = wordRegexp([\"abs\", \"acos\", \"allShortestPaths\", \"asin\", \"atan\", \"atan2\", \"avg\", \"ceil\", \"coalesce\", \"collect\", \"cos\", \"cot\", \"count\", \"degrees\", \"e\", \"endnode\", \"exp\", \"extract\", \"filter\", \"floor\", \"haversin\", \"head\", \"id\", \"keys\", \"labels\", \"last\", \"left\", \"length\", \"log\", \"log10\", \"lower\", \"ltrim\", \"max\", \"min\", \"node\", \"nodes\", \"percentileCont\", \"percentileDisc\", \"pi\", \"radians\", \"rand\", \"range\", \"reduce\", \"rel\", \"relationship\", \"relationships\", \"replace\", \"reverse\", \"right\", \"round\", \"rtrim\", \"shortestPath\", \"sign\", \"sin\", \"size\", \"split\", \"sqrt\", \"startnode\", \"stdev\", \"stdevp\", \"str\", \"substring\", \"sum\", \"tail\", \"tan\", \"timestamp\", \"toFloat\", \"toInt\", \"toString\", \"trim\", \"type\", \"upper\"]);\nvar preds = wordRegexp([\"all\", \"and\", \"any\", \"contains\", \"exists\", \"has\", \"in\", \"none\", \"not\", \"or\", \"single\", \"xor\"]);\nvar keywords = wordRegexp([\"as\", \"asc\", \"ascending\", \"assert\", \"by\", \"case\", \"commit\", \"constraint\", \"create\", \"csv\", \"cypher\", \"delete\", \"desc\", \"descending\", \"detach\", \"distinct\", \"drop\", \"else\", \"end\", \"ends\", \"explain\", \"false\", \"fieldterminator\", \"foreach\", \"from\", \"headers\", \"in\", \"index\", \"is\", \"join\", \"limit\", \"load\", \"match\", \"merge\", \"null\", \"on\", \"optional\", \"order\", \"periodic\", \"profile\", \"remove\", \"return\", \"scan\", \"set\", \"skip\", \"start\", \"starts\", \"then\", \"true\", \"union\", \"unique\", \"unwind\", \"using\", \"when\", \"where\", \"with\", \"call\", \"yield\"]);\nvar systemKeywords = wordRegexp([\"access\", \"active\", \"assign\", \"all\", \"alter\", \"as\", \"catalog\", \"change\", \"copy\", \"create\", \"constraint\", \"constraints\", \"current\", \"database\", \"databases\", \"dbms\", \"default\", \"deny\", \"drop\", \"element\", \"elements\", \"exists\", \"from\", \"grant\", \"graph\", \"graphs\", \"if\", \"index\", \"indexes\", \"label\", \"labels\", \"management\", \"match\", \"name\", \"names\", \"new\", \"node\", \"nodes\", \"not\", \"of\", \"on\", \"or\", \"password\", \"populated\", \"privileges\", \"property\", \"read\", \"relationship\", \"relationships\", \"remove\", \"replace\", \"required\", \"revoke\", \"role\", \"roles\", \"set\", \"show\", \"start\", \"status\", \"stop\", \"suspended\", \"to\", \"traverse\", \"type\", \"types\", \"user\", \"users\", \"with\", \"write\"]);\nvar operatorChars = /[*+\\-<>=&|~%^]/;\n\nexport const cypher = {\n name: \"cypher\",\n startState: function() {\n return {\n tokenize: tokenBase,\n context: null,\n indent: 0,\n col: 0\n };\n },\n token: function(stream, state) {\n if (stream.sol()) {\n if (state.context && (state.context.align == null)) {\n state.context.align = false;\n }\n state.indent = stream.indentation();\n }\n if (stream.eatSpace()) {\n return null;\n }\n var style = state.tokenize(stream, state);\n if (style !== \"comment\" && state.context && (state.context.align == null) && state.context.type !== \"pattern\") {\n state.context.align = true;\n }\n if (curPunc === \"(\") {\n pushContext(state, \")\", stream.column());\n } else if (curPunc === \"[\") {\n pushContext(state, \"]\", stream.column());\n } else if (curPunc === \"{\") {\n pushContext(state, \"}\", stream.column());\n } else if (/[\\]\\}\\)]/.test(curPunc)) {\n while (state.context && state.context.type === \"pattern\") {\n popContext(state);\n }\n if (state.context && curPunc === state.context.type) {\n popContext(state);\n }\n } else if (curPunc === \".\" && state.context && state.context.type === \"pattern\") {\n popContext(state);\n } else if (/atom|string|variable/.test(style) && state.context) {\n if (/[\\}\\]]/.test(state.context.type)) {\n pushContext(state, \"pattern\", stream.column());\n } else if (state.context.type === \"pattern\" && !state.context.align) {\n state.context.align = true;\n state.context.col = stream.column();\n }\n }\n return style;\n },\n indent: function(state, textAfter, cx) {\n var firstChar = textAfter && textAfter.charAt(0);\n var context = state.context;\n if (/[\\]\\}]/.test(firstChar)) {\n while (context && context.type === \"pattern\") {\n context = context.prev;\n }\n }\n var closing = context && firstChar === context.type;\n if (!context) return 0;\n if (context.type === \"keywords\") return null\n if (context.align) return context.col + (closing ? 0 : 1);\n return context.indent + (closing ? 0 : cx.unit);\n }\n};\n"],"names":["curPunc","wordRegexp","words","RegExp","join","tokenBase","stream","ch","next","match","test","eat","skipToEnd","operatorChars","eatWhile","word","current","funcs","preds","keywords","systemKeywords","pushContext","state","type","col","context","prev","indent","popContext","cypher","name","startState","tokenize","token","sol","align","indentation","eatSpace","style","column","textAfter","cx","firstChar","charAt","closing","unit"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/2519.index.js b/book/_build/html/_static/2519.index.js
new file mode 100644
index 0000000..830bc69
--- /dev/null
+++ b/book/_build/html/_static/2519.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[2519],{62519:(e,t,a)=>{a.r(t),a.d(t,{spreadsheet:()=>s});const s={name:"spreadsheet",startState:function(){return{stringType:null,stack:[]}},token:function(e,t){if(e){switch(0===t.stack.length&&('"'!=e.peek()&&"'"!=e.peek()||(t.stringType=e.peek(),e.next(),t.stack.unshift("string"))),t.stack[0]){case"string":for(;"string"===t.stack[0]&&!e.eol();)e.peek()===t.stringType?(e.next(),t.stack.shift()):"\\"===e.peek()?(e.next(),e.next()):e.match(/^.[^\\\"\']*/);return"string";case"characterClass":for(;"characterClass"===t.stack[0]&&!e.eol();)e.match(/^[^\]\\]+/)||e.match(/^\\./)||t.stack.shift();return"operator"}var a=e.peek();switch(a){case"[":return e.next(),t.stack.unshift("characterClass"),"bracket";case":":return e.next(),"operator";case"\\":return e.match(/\\[a-z]+/)?"string.special":(e.next(),"atom");case".":case",":case";":case"*":case"-":case"+":case"^":case"<":case"/":case"=":return e.next(),"atom";case"$":return e.next(),"builtin"}return e.match(/\d+/)?e.match(/^\w+/)?"error":"number":e.match(/^[a-zA-Z_]\w*/)?e.match(/(?=[\(.])/,!1)?"keyword":"variable":-1!=["[","]","(",")","{","}"].indexOf(a)?(e.next(),"bracket"):(e.eatSpace()||e.next(),null)}}}}}]);
+//# sourceMappingURL=2519.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/2519.index.js.map b/book/_build/html/_static/2519.index.js.map
new file mode 100644
index 0000000..d373d5f
--- /dev/null
+++ b/book/_build/html/_static/2519.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"2519.index.js","mappings":"iIAAO,MAAMA,EAAc,CACzBC,KAAM,cAENC,WAAY,WACV,MAAO,CACLC,WAAY,KACZC,MAAO,GAEX,EACAC,MAAO,SAAUC,EAAQC,GACvB,GAAKD,EAAL,CAcA,OAX2B,IAAvBC,EAAMH,MAAMI,SAEQ,KAAjBF,EAAOG,QAAoC,KAAjBH,EAAOG,SACpCF,EAAMJ,WAAaG,EAAOG,OAC1BH,EAAOI,OACPH,EAAMH,MAAMO,QAAQ,YAMhBJ,EAAMH,MAAM,IACpB,IAAK,SACH,KAA0B,WAAnBG,EAAMH,MAAM,KAAoBE,EAAOM,OACxCN,EAAOG,SAAWF,EAAMJ,YAC1BG,EAAOI,OACPH,EAAMH,MAAMS,SACe,OAAlBP,EAAOG,QAChBH,EAAOI,OACPJ,EAAOI,QAEPJ,EAAOQ,MAAM,gBAGjB,MAAO,SAET,IAAK,iBACH,KAA0B,mBAAnBP,EAAMH,MAAM,KAA4BE,EAAOM,OAC9CN,EAAOQ,MAAM,cAAgBR,EAAOQ,MAAM,SAC9CP,EAAMH,MAAMS,QAEhB,MAAO,WAGT,IAAIJ,EAAOH,EAAOG,OAGlB,OAAQA,GACR,IAAK,IAGH,OAFAH,EAAOI,OACPH,EAAMH,MAAMO,QAAQ,kBACb,UACT,IAAK,IAEH,OADAL,EAAOI,OACA,WACT,IAAK,KACH,OAAIJ,EAAOQ,MAAM,YAAoB,kBAEnCR,EAAOI,OACA,QAEX,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IAEH,OADAJ,EAAOI,OACA,OACT,IAAK,IAEH,OADAJ,EAAOI,OACA,UAGT,OAAIJ,EAAOQ,MAAM,OACXR,EAAOQ,MAAM,QAAgB,QAC1B,SACER,EAAOQ,MAAM,iBAClBR,EAAOQ,MAAM,aAAa,GAAe,UACtC,YACmD,GAAjD,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,KAAKC,QAAQN,IAChDH,EAAOI,OACA,YACGJ,EAAOU,YACjBV,EAAOI,OAEF,KAnFY,CAoFrB,E","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/spreadsheet.js"],"sourcesContent":["export const spreadsheet = {\n name: \"spreadsheet\",\n\n startState: function () {\n return {\n stringType: null,\n stack: []\n };\n },\n token: function (stream, state) {\n if (!stream) return;\n\n //check for state changes\n if (state.stack.length === 0) {\n //strings\n if ((stream.peek() == '\"') || (stream.peek() == \"'\")) {\n state.stringType = stream.peek();\n stream.next(); // Skip quote\n state.stack.unshift(\"string\");\n }\n }\n\n //return state\n //stack has\n switch (state.stack[0]) {\n case \"string\":\n while (state.stack[0] === \"string\" && !stream.eol()) {\n if (stream.peek() === state.stringType) {\n stream.next(); // Skip quote\n state.stack.shift(); // Clear flag\n } else if (stream.peek() === \"\\\\\") {\n stream.next();\n stream.next();\n } else {\n stream.match(/^.[^\\\\\\\"\\']*/);\n }\n }\n return \"string\";\n\n case \"characterClass\":\n while (state.stack[0] === \"characterClass\" && !stream.eol()) {\n if (!(stream.match(/^[^\\]\\\\]+/) || stream.match(/^\\\\./)))\n state.stack.shift();\n }\n return \"operator\";\n }\n\n var peek = stream.peek();\n\n //no stack\n switch (peek) {\n case \"[\":\n stream.next();\n state.stack.unshift(\"characterClass\");\n return \"bracket\";\n case \":\":\n stream.next();\n return \"operator\";\n case \"\\\\\":\n if (stream.match(/\\\\[a-z]+/)) return \"string.special\";\n else {\n stream.next();\n return \"atom\";\n }\n case \".\":\n case \",\":\n case \";\":\n case \"*\":\n case \"-\":\n case \"+\":\n case \"^\":\n case \"<\":\n case \"/\":\n case \"=\":\n stream.next();\n return \"atom\";\n case \"$\":\n stream.next();\n return \"builtin\";\n }\n\n if (stream.match(/\\d+/)) {\n if (stream.match(/^\\w+/)) return \"error\";\n return \"number\";\n } else if (stream.match(/^[a-zA-Z_]\\w*/)) {\n if (stream.match(/(?=[\\(.])/, false)) return \"keyword\";\n return \"variable\";\n } else if ([\"[\", \"]\", \"(\", \")\", \"{\", \"}\"].indexOf(peek) != -1) {\n stream.next();\n return \"bracket\";\n } else if (!stream.eatSpace()) {\n stream.next();\n }\n return null;\n }\n};\n"],"names":["spreadsheet","name","startState","stringType","stack","token","stream","state","length","peek","next","unshift","eol","shift","match","indexOf","eatSpace"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/2719.index.js b/book/_build/html/_static/2719.index.js
new file mode 100644
index 0000000..6a4474f
--- /dev/null
+++ b/book/_build/html/_static/2719.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[2719],{22719:(e,t,n)=>{function r(e){return new RegExp("^(("+e.join(")|(")+"))\\b")}n.r(t),n.d(t,{cython:()=>u,mkPython:()=>l,python:()=>s});var i=r(["and","or","not","is"]),a=["as","assert","break","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","lambda","pass","raise","return","try","while","with","yield","in","False","True"],o=["abs","all","any","bin","bool","bytearray","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip","__import__","NotImplemented","Ellipsis","__debug__"];function c(e){return e.scopes[e.scopes.length-1]}function l(e){for(var t="error",n=e.delimiters||e.singleDelimiters||/^[\(\)\[\]\{\}@,:`=;\.\\]/,l=[e.singleOperators,e.doubleOperators,e.doubleDelimiters,e.tripleDelimiters,e.operators||/^([-+*/%\/&|^]=?|[<>=]+|\/\/=?|\*\*=?|!=|[~!@]|\.\.\.)/],s=0;si?x(e,n):a0&&v(e,n)&&(o+=" "+t),o}return k(e,n)}function k(r,a,o){if(r.eatSpace())return null;if(!o&&r.match(/^#.*/))return"comment";if(r.match(/^[0-9\.]/,!1)){var c=!1;if(r.match(/^[\d_]*\.\d+(e[\+\-]?\d+)?/i)&&(c=!0),r.match(/^[\d_]+\.\d*/)&&(c=!0),r.match(/^\.\d+/)&&(c=!0),c)return r.eat(/J/i),"number";var s=!1;if(r.match(/^0x[0-9a-f_]+/i)&&(s=!0),r.match(/^0b[01_]+/i)&&(s=!0),r.match(/^0o[0-7_]+/i)&&(s=!0),r.match(/^[1-9][\d_]*(e[\+\-]?[\d_]+)?/)&&(r.eat(/J/i),s=!0),r.match(/^0(?![\dx])/i)&&(s=!0),s)return r.eat(/L/i),"number"}if(r.match(h))return-1!==r.current().toLowerCase().indexOf("f")?(a.tokenize=function(n,r){for(;"rubf".indexOf(n.charAt(0).toLowerCase())>=0;)n=n.substr(1);var i=1==n.length,a="string";function o(e){return function(t,n){var r=k(t,n,!0);return"punctuation"==r&&("{"==t.current()?n.tokenize=o(e+1):"}"==t.current()&&(n.tokenize=e>1?o(e-1):c)),r}}function c(c,l){for(;!c.eol();)if(c.eatWhile(/[^'"\{\}\\]/),c.eat("\\")){if(c.next(),i&&c.eol())return a}else{if(c.match(n))return l.tokenize=r,a;if(c.match("{{"))return a;if(c.match("{",!1))return l.tokenize=o(0),c.current()?a:l.tokenize(c,l);if(c.match("}}"))return a;if(c.match("}"))return t;c.eat(/['"]/)}if(i){if(e.singleLineStringErrors)return t;l.tokenize=r}return a}return c.isString=!0,c}(r.current(),a.tokenize),a.tokenize(r,a)):(a.tokenize=function(n,r){for(;"rubf".indexOf(n.charAt(0).toLowerCase())>=0;)n=n.substr(1);var i=1==n.length,a="string";function o(o,c){for(;!o.eol();)if(o.eatWhile(/[^'"\\]/),o.eat("\\")){if(o.next(),i&&o.eol())return a}else{if(o.match(n))return c.tokenize=r,a;o.eat(/['"]/)}if(i){if(e.singleLineStringErrors)return t;c.tokenize=r}return a}return o.isString=!0,o}(r.current(),a.tokenize),a.tokenize(r,a));for(var u=0;u1&&c(t).offset>n;){if("py"!=c(t).type)return!0;t.scopes.pop()}return c(t).offset!=n}return{name:"python",startState:function(){return{tokenize:g,scopes:[{offset:0,type:"py",align:null}],indent:0,lastToken:null,lambda:!1,dedent:0}},token:function(e,n){var r=n.errorToken;r&&(n.errorToken=!1);var i=function(e,n){e.sol()&&(n.beginningOfLine=!0,n.dedent=!1);var r=n.tokenize(e,n),i=e.current();if(n.beginningOfLine&&"@"==i)return e.match(m,!1)?"meta":d?"operator":t;if(/\S/.test(i)&&(n.beginningOfLine=!1),"variable"!=r&&"builtin"!=r||"meta"!=n.lastToken||(r="meta"),"pass"!=i&&"return"!=i||(n.dedent=!0),"lambda"==i&&(n.lambda=!0),":"==i&&!n.lambda&&"py"==c(n).type&&e.match(/^\s*(?:#|$)/,!1)&&x(e,n),1==i.length&&!/string|comment/.test(r)){var a="[({".indexOf(i);if(-1!=a&&function(e,t,n){var r=e.match(/^[\s\[\{\(]*(?:#|$)/,!1)?null:e.column()+1;t.scopes.push({offset:t.indent+(u||e.indentUnit),type:n,align:r})}(e,n,"])}".slice(a,a+1)),-1!=(a="])}".indexOf(i))){if(c(n).type!=i)return t;n.indent=n.scopes.pop().offset-(u||e.indentUnit)}}return n.dedent&&e.eol()&&"py"==c(n).type&&n.scopes.length>1&&n.scopes.pop(),r}(e,n);return i&&"comment"!=i&&(n.lastToken="keyword"==i||"punctuation"==i?e.current():i),"punctuation"==i&&(i=null),e.eol()&&n.lambda&&(n.lambda=!1),r?t:i},indent:function(e,t,n){if(e.tokenize!=g)return e.tokenize.isString?null:0;var r=c(e),i=r.type==t.charAt(0)||"py"==r.type&&!e.dedent&&/^(else:|elif |except |finally:)/.test(t);return null!=r.align?r.align-(i?1:0):r.offset-(i?u||n.unit:0)},languageData:{autocomplete:a.concat(o).concat(["exec","print"]),indentOnInput:/^\s*([\}\]\)]|else:|elif |except |finally:)$/,commentTokens:{line:"#"},closeBrackets:{brackets:["(","[","{","'",'"',"'''",'"""']}}}}const s=l({}),u=l({extra_keywords:("by cdef cimport cpdef ctypedef enum except extern gil include nogil property public readonly struct union DEF IF ELIF ELSE","by cdef cimport cpdef ctypedef enum except extern gil include nogil property public readonly struct union DEF IF ELIF ELSE".split(" "))})}}]);
+//# sourceMappingURL=2719.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/2719.index.js.map b/book/_build/html/_static/2719.index.js.map
new file mode 100644
index 0000000..ba6ab9f
--- /dev/null
+++ b/book/_build/html/_static/2719.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"2719.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/python.js"],"sourcesContent":["function wordRegexp(words) {\n return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\");\n}\n\nvar wordOperators = wordRegexp([\"and\", \"or\", \"not\", \"is\"]);\nvar commonKeywords = [\"as\", \"assert\", \"break\", \"class\", \"continue\",\n \"def\", \"del\", \"elif\", \"else\", \"except\", \"finally\",\n \"for\", \"from\", \"global\", \"if\", \"import\",\n \"lambda\", \"pass\", \"raise\", \"return\",\n \"try\", \"while\", \"with\", \"yield\", \"in\", \"False\", \"True\"];\nvar commonBuiltins = [\"abs\", \"all\", \"any\", \"bin\", \"bool\", \"bytearray\", \"callable\", \"chr\",\n \"classmethod\", \"compile\", \"complex\", \"delattr\", \"dict\", \"dir\", \"divmod\",\n \"enumerate\", \"eval\", \"filter\", \"float\", \"format\", \"frozenset\",\n \"getattr\", \"globals\", \"hasattr\", \"hash\", \"help\", \"hex\", \"id\",\n \"input\", \"int\", \"isinstance\", \"issubclass\", \"iter\", \"len\",\n \"list\", \"locals\", \"map\", \"max\", \"memoryview\", \"min\", \"next\",\n \"object\", \"oct\", \"open\", \"ord\", \"pow\", \"property\", \"range\",\n \"repr\", \"reversed\", \"round\", \"set\", \"setattr\", \"slice\",\n \"sorted\", \"staticmethod\", \"str\", \"sum\", \"super\", \"tuple\",\n \"type\", \"vars\", \"zip\", \"__import__\", \"NotImplemented\",\n \"Ellipsis\", \"__debug__\"];\n\nfunction top(state) {\n return state.scopes[state.scopes.length - 1];\n}\n\nexport function mkPython(parserConf) {\n var ERRORCLASS = \"error\";\n\n var delimiters = parserConf.delimiters || parserConf.singleDelimiters || /^[\\(\\)\\[\\]\\{\\}@,:`=;\\.\\\\]/;\n // (Backwards-compatibility with old, cumbersome config system)\n var operators = [parserConf.singleOperators, parserConf.doubleOperators, parserConf.doubleDelimiters, parserConf.tripleDelimiters,\n parserConf.operators || /^([-+*/%\\/&|^]=?|[<>=]+|\\/\\/=?|\\*\\*=?|!=|[~!@]|\\.\\.\\.)/]\n for (var i = 0; i < operators.length; i++) if (!operators[i]) operators.splice(i--, 1)\n\n var hangingIndent = parserConf.hangingIndent;\n\n var myKeywords = commonKeywords, myBuiltins = commonBuiltins;\n if (parserConf.extra_keywords != undefined)\n myKeywords = myKeywords.concat(parserConf.extra_keywords);\n\n if (parserConf.extra_builtins != undefined)\n myBuiltins = myBuiltins.concat(parserConf.extra_builtins);\n\n var py3 = !(parserConf.version && Number(parserConf.version) < 3)\n if (py3) {\n // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator\n var identifiers = parserConf.identifiers|| /^[_A-Za-z\\u00A1-\\uFFFF][_A-Za-z0-9\\u00A1-\\uFFFF]*/;\n myKeywords = myKeywords.concat([\"nonlocal\", \"None\", \"aiter\", \"anext\", \"async\", \"await\", \"breakpoint\", \"match\", \"case\"]);\n myBuiltins = myBuiltins.concat([\"ascii\", \"bytes\", \"exec\", \"print\"]);\n var stringPrefixes = new RegExp(\"^(([rbuf]|(br)|(rb)|(fr)|(rf))?('{3}|\\\"{3}|['\\\"]))\", \"i\");\n } else {\n var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/;\n myKeywords = myKeywords.concat([\"exec\", \"print\"]);\n myBuiltins = myBuiltins.concat([\"apply\", \"basestring\", \"buffer\", \"cmp\", \"coerce\", \"execfile\",\n \"file\", \"intern\", \"long\", \"raw_input\", \"reduce\", \"reload\",\n \"unichr\", \"unicode\", \"xrange\", \"None\"]);\n var stringPrefixes = new RegExp(\"^(([rubf]|(ur)|(br))?('{3}|\\\"{3}|['\\\"]))\", \"i\");\n }\n var keywords = wordRegexp(myKeywords);\n var builtins = wordRegexp(myBuiltins);\n\n // tokenizers\n function tokenBase(stream, state) {\n var sol = stream.sol() && state.lastToken != \"\\\\\"\n if (sol) state.indent = stream.indentation()\n // Handle scope changes\n if (sol && top(state).type == \"py\") {\n var scopeOffset = top(state).offset;\n if (stream.eatSpace()) {\n var lineOffset = stream.indentation();\n if (lineOffset > scopeOffset)\n pushPyScope(stream, state);\n else if (lineOffset < scopeOffset && dedent(stream, state) && stream.peek() != \"#\")\n state.errorToken = true;\n return null;\n } else {\n var style = tokenBaseInner(stream, state);\n if (scopeOffset > 0 && dedent(stream, state))\n style += \" \" + ERRORCLASS;\n return style;\n }\n }\n return tokenBaseInner(stream, state);\n }\n\n function tokenBaseInner(stream, state, inFormat) {\n if (stream.eatSpace()) return null;\n\n // Handle Comments\n if (!inFormat && stream.match(/^#.*/)) return \"comment\";\n\n // Handle Number Literals\n if (stream.match(/^[0-9\\.]/, false)) {\n var floatLiteral = false;\n // Floats\n if (stream.match(/^[\\d_]*\\.\\d+(e[\\+\\-]?\\d+)?/i)) { floatLiteral = true; }\n if (stream.match(/^[\\d_]+\\.\\d*/)) { floatLiteral = true; }\n if (stream.match(/^\\.\\d+/)) { floatLiteral = true; }\n if (floatLiteral) {\n // Float literals may be \"imaginary\"\n stream.eat(/J/i);\n return \"number\";\n }\n // Integers\n var intLiteral = false;\n // Hex\n if (stream.match(/^0x[0-9a-f_]+/i)) intLiteral = true;\n // Binary\n if (stream.match(/^0b[01_]+/i)) intLiteral = true;\n // Octal\n if (stream.match(/^0o[0-7_]+/i)) intLiteral = true;\n // Decimal\n if (stream.match(/^[1-9][\\d_]*(e[\\+\\-]?[\\d_]+)?/)) {\n // Decimal literals may be \"imaginary\"\n stream.eat(/J/i);\n // TODO - Can you have imaginary longs?\n intLiteral = true;\n }\n // Zero by itself with no other piece of number.\n if (stream.match(/^0(?![\\dx])/i)) intLiteral = true;\n if (intLiteral) {\n // Integer literals may be \"long\"\n stream.eat(/L/i);\n return \"number\";\n }\n }\n\n // Handle Strings\n if (stream.match(stringPrefixes)) {\n var isFmtString = stream.current().toLowerCase().indexOf('f') !== -1;\n if (!isFmtString) {\n state.tokenize = tokenStringFactory(stream.current(), state.tokenize);\n return state.tokenize(stream, state);\n } else {\n state.tokenize = formatStringFactory(stream.current(), state.tokenize);\n return state.tokenize(stream, state);\n }\n }\n\n for (var i = 0; i < operators.length; i++)\n if (stream.match(operators[i])) return \"operator\"\n\n if (stream.match(delimiters)) return \"punctuation\";\n\n if (state.lastToken == \".\" && stream.match(identifiers))\n return \"property\";\n\n if (stream.match(keywords) || stream.match(wordOperators))\n return \"keyword\";\n\n if (stream.match(builtins))\n return \"builtin\";\n\n if (stream.match(/^(self|cls)\\b/))\n return \"self\";\n\n if (stream.match(identifiers)) {\n if (state.lastToken == \"def\" || state.lastToken == \"class\")\n return \"def\";\n return \"variable\";\n }\n\n // Handle non-detected items\n stream.next();\n return inFormat ? null :ERRORCLASS;\n }\n\n function formatStringFactory(delimiter, tokenOuter) {\n while (\"rubf\".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)\n delimiter = delimiter.substr(1);\n\n var singleline = delimiter.length == 1;\n var OUTCLASS = \"string\";\n\n function tokenNestedExpr(depth) {\n return function(stream, state) {\n var inner = tokenBaseInner(stream, state, true)\n if (inner == \"punctuation\") {\n if (stream.current() == \"{\") {\n state.tokenize = tokenNestedExpr(depth + 1)\n } else if (stream.current() == \"}\") {\n if (depth > 1) state.tokenize = tokenNestedExpr(depth - 1)\n else state.tokenize = tokenString\n }\n }\n return inner\n }\n }\n\n function tokenString(stream, state) {\n while (!stream.eol()) {\n stream.eatWhile(/[^'\"\\{\\}\\\\]/);\n if (stream.eat(\"\\\\\")) {\n stream.next();\n if (singleline && stream.eol())\n return OUTCLASS;\n } else if (stream.match(delimiter)) {\n state.tokenize = tokenOuter;\n return OUTCLASS;\n } else if (stream.match('{{')) {\n // ignore {{ in f-str\n return OUTCLASS;\n } else if (stream.match('{', false)) {\n // switch to nested mode\n state.tokenize = tokenNestedExpr(0)\n if (stream.current()) return OUTCLASS;\n else return state.tokenize(stream, state)\n } else if (stream.match('}}')) {\n return OUTCLASS;\n } else if (stream.match('}')) {\n // single } in f-string is an error\n return ERRORCLASS;\n } else {\n stream.eat(/['\"]/);\n }\n }\n if (singleline) {\n if (parserConf.singleLineStringErrors)\n return ERRORCLASS;\n else\n state.tokenize = tokenOuter;\n }\n return OUTCLASS;\n }\n tokenString.isString = true;\n return tokenString;\n }\n\n function tokenStringFactory(delimiter, tokenOuter) {\n while (\"rubf\".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)\n delimiter = delimiter.substr(1);\n\n var singleline = delimiter.length == 1;\n var OUTCLASS = \"string\";\n\n function tokenString(stream, state) {\n while (!stream.eol()) {\n stream.eatWhile(/[^'\"\\\\]/);\n if (stream.eat(\"\\\\\")) {\n stream.next();\n if (singleline && stream.eol())\n return OUTCLASS;\n } else if (stream.match(delimiter)) {\n state.tokenize = tokenOuter;\n return OUTCLASS;\n } else {\n stream.eat(/['\"]/);\n }\n }\n if (singleline) {\n if (parserConf.singleLineStringErrors)\n return ERRORCLASS;\n else\n state.tokenize = tokenOuter;\n }\n return OUTCLASS;\n }\n tokenString.isString = true;\n return tokenString;\n }\n\n function pushPyScope(stream, state) {\n while (top(state).type != \"py\") state.scopes.pop()\n state.scopes.push({offset: top(state).offset + stream.indentUnit,\n type: \"py\",\n align: null})\n }\n\n function pushBracketScope(stream, state, type) {\n var align = stream.match(/^[\\s\\[\\{\\(]*(?:#|$)/, false) ? null : stream.column() + 1\n state.scopes.push({offset: state.indent + (hangingIndent || stream.indentUnit),\n type: type,\n align: align})\n }\n\n function dedent(stream, state) {\n var indented = stream.indentation();\n while (state.scopes.length > 1 && top(state).offset > indented) {\n if (top(state).type != \"py\") return true;\n state.scopes.pop();\n }\n return top(state).offset != indented;\n }\n\n function tokenLexer(stream, state) {\n if (stream.sol()) {\n state.beginningOfLine = true;\n state.dedent = false;\n }\n\n var style = state.tokenize(stream, state);\n var current = stream.current();\n\n // Handle decorators\n if (state.beginningOfLine && current == \"@\")\n return stream.match(identifiers, false) ? \"meta\" : py3 ? \"operator\" : ERRORCLASS;\n\n if (/\\S/.test(current)) state.beginningOfLine = false;\n\n if ((style == \"variable\" || style == \"builtin\")\n && state.lastToken == \"meta\")\n style = \"meta\";\n\n // Handle scope changes.\n if (current == \"pass\" || current == \"return\")\n state.dedent = true;\n\n if (current == \"lambda\") state.lambda = true;\n if (current == \":\" && !state.lambda && top(state).type == \"py\" && stream.match(/^\\s*(?:#|$)/, false))\n pushPyScope(stream, state);\n\n if (current.length == 1 && !/string|comment/.test(style)) {\n var delimiter_index = \"[({\".indexOf(current);\n if (delimiter_index != -1)\n pushBracketScope(stream, state, \"])}\".slice(delimiter_index, delimiter_index+1));\n\n delimiter_index = \"])}\".indexOf(current);\n if (delimiter_index != -1) {\n if (top(state).type == current) state.indent = state.scopes.pop().offset - (hangingIndent || stream.indentUnit)\n else return ERRORCLASS;\n }\n }\n if (state.dedent && stream.eol() && top(state).type == \"py\" && state.scopes.length > 1)\n state.scopes.pop();\n\n return style;\n }\n\n return {\n name: \"python\",\n\n startState: function() {\n return {\n tokenize: tokenBase,\n scopes: [{offset: 0, type: \"py\", align: null}],\n indent: 0,\n lastToken: null,\n lambda: false,\n dedent: 0\n };\n },\n\n token: function(stream, state) {\n var addErr = state.errorToken;\n if (addErr) state.errorToken = false;\n var style = tokenLexer(stream, state);\n\n if (style && style != \"comment\")\n state.lastToken = (style == \"keyword\" || style == \"punctuation\") ? stream.current() : style;\n if (style == \"punctuation\") style = null;\n\n if (stream.eol() && state.lambda)\n state.lambda = false;\n return addErr ? ERRORCLASS : style;\n },\n\n indent: function(state, textAfter, cx) {\n if (state.tokenize != tokenBase)\n return state.tokenize.isString ? null : 0;\n\n var scope = top(state)\n var closing = scope.type == textAfter.charAt(0) ||\n scope.type == \"py\" && !state.dedent && /^(else:|elif |except |finally:)/.test(textAfter)\n if (scope.align != null)\n return scope.align - (closing ? 1 : 0)\n else\n return scope.offset - (closing ? hangingIndent || cx.unit : 0)\n },\n\n languageData: {\n autocomplete: commonKeywords.concat(commonBuiltins).concat([\"exec\", \"print\"]),\n indentOnInput: /^\\s*([\\}\\]\\)]|else:|elif |except |finally:)$/,\n commentTokens: {line: \"#\"},\n closeBrackets: {brackets: [\"(\", \"[\", \"{\", \"'\", '\"', \"'''\", '\"\"\"']}\n }\n };\n};\n\nvar words = function(str) { return str.split(\" \"); };\n\nexport const python = mkPython({})\n\nexport const cython = mkPython({\n extra_keywords: words(\"by cdef cimport cpdef ctypedef enum except \"+\n \"extern gil include nogil property public \"+\n \"readonly struct union DEF IF ELIF ELSE\")\n})\n"],"names":["wordRegexp","words","RegExp","join","wordOperators","commonKeywords","commonBuiltins","top","state","scopes","length","mkPython","parserConf","ERRORCLASS","delimiters","singleDelimiters","operators","singleOperators","doubleOperators","doubleDelimiters","tripleDelimiters","i","splice","hangingIndent","myKeywords","myBuiltins","undefined","extra_keywords","concat","extra_builtins","py3","version","Number","identifiers","stringPrefixes","keywords","builtins","tokenBase","stream","sol","lastToken","indent","indentation","type","scopeOffset","offset","eatSpace","lineOffset","pushPyScope","dedent","peek","errorToken","style","tokenBaseInner","inFormat","match","floatLiteral","eat","intLiteral","current","toLowerCase","indexOf","tokenize","delimiter","tokenOuter","charAt","substr","singleline","OUTCLASS","tokenNestedExpr","depth","inner","tokenString","eol","eatWhile","next","singleLineStringErrors","isString","formatStringFactory","tokenStringFactory","pop","push","indentUnit","align","indented","name","startState","lambda","token","addErr","beginningOfLine","test","delimiter_index","column","pushBracketScope","slice","tokenLexer","textAfter","cx","scope","closing","unit","languageData","autocomplete","indentOnInput","commentTokens","line","closeBrackets","brackets","python","cython","split"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/2766.index.js b/book/_build/html/_static/2766.index.js
new file mode 100644
index 0000000..3c0c245
--- /dev/null
+++ b/book/_build/html/_static/2766.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[2766],{42766:(e,t,n)=>{function r(e){for(var t={},n=e.split(" "),r=0;rs});const i={keywords:r("DEFINITIONS OBJECTS IF DERIVED INFORMATION ACTION REPLY ANY NAMED CHARACTERIZED BEHAVIOUR REGISTERED WITH AS IDENTIFIED CONSTRAINED BY PRESENT BEGIN IMPORTS FROM UNITS SYNTAX MIN-ACCESS MAX-ACCESS MINACCESS MAXACCESS REVISION STATUS DESCRIPTION SEQUENCE SET COMPONENTS OF CHOICE DistinguishedName ENUMERATED SIZE MODULE END INDEX AUGMENTS EXTENSIBILITY IMPLIED EXPORTS"),cmipVerbs:r("ACTIONS ADD GET NOTIFICATIONS REPLACE REMOVE"),compareTypes:r("OPTIONAL DEFAULT MANAGED MODULE-TYPE MODULE_IDENTITY MODULE-COMPLIANCE OBJECT-TYPE OBJECT-IDENTITY OBJECT-COMPLIANCE MODE CONFIRMED CONDITIONAL SUBORDINATE SUPERIOR CLASS TRUE FALSE NULL TEXTUAL-CONVENTION"),status:r("current deprecated mandatory obsolete"),tags:r("APPLICATION AUTOMATIC EXPLICIT IMPLICIT PRIVATE TAGS UNIVERSAL"),storage:r("BOOLEAN INTEGER OBJECT IDENTIFIER BIT OCTET STRING UTCTime InterfaceIndex IANAifType CMIP-Attribute REAL PACKAGE PACKAGES IpAddress PhysAddress NetworkAddress BITS BMPString TimeStamp TimeTicks TruthValue RowStatus DisplayString GeneralString GraphicString IA5String NumericString PrintableString SnmpAdminString TeletexString UTF8String VideotexString VisibleString StringStore ISO646String T61String UniversalString Unsigned32 Integer32 Gauge Gauge32 Counter Counter32 Counter64"),modifier:r("ATTRIBUTE ATTRIBUTES MANDATORY-GROUP MANDATORY-GROUPS GROUP GROUPS ELEMENTS EQUALITY ORDERING SUBSTRINGS DEFINED"),accessTypes:r("not-accessible accessible-for-notify read-only read-create read-write"),multiLineStrings:!0};function s(e){var t,n=e.keywords||i.keywords,r=e.cmipVerbs||i.cmipVerbs,s=e.compareTypes||i.compareTypes,a=e.status||i.status,E=e.tags||i.tags,I=e.storage||i.storage,o=e.modifier||i.modifier,T=e.accessTypes||i.accessTypes,S=e.multiLineStrings||i.multiLineStrings,u=!1!==e.indentStatements,l=/[\|\^]/;function A(e,i){var u,A=e.next();if('"'==A||"'"==A)return i.tokenize=(u=A,function(e,t){for(var n,r=!1,i=!1;null!=(n=e.next());){if(n==u&&!r){var s=e.peek();s&&("b"!=(s=s.toLowerCase())&&"h"!=s&&"o"!=s||e.next()),i=!0;break}r=!r&&"\\"==n}return(i||!r&&!S)&&(t.tokenize=null),"string"}),i.tokenize(e,i);if(/[\[\]\(\){}:=,;]/.test(A))return t=A,"punctuation";if("-"==A&&e.eat("-"))return e.skipToEnd(),"comment";if(/\d/.test(A))return e.eatWhile(/[\w\.]/),"number";if(l.test(A))return e.eatWhile(l),"operator";e.eatWhile(/[\w\-]/);var N=e.current();return n.propertyIsEnumerable(N)?"keyword":r.propertyIsEnumerable(N)?"variableName":s.propertyIsEnumerable(N)?"atom":a.propertyIsEnumerable(N)?"comment":E.propertyIsEnumerable(N)?"typeName":I.propertyIsEnumerable(N)||o.propertyIsEnumerable(N)||T.propertyIsEnumerable(N)?"modifier":"variableName"}function N(e,t,n,r,i){this.indented=e,this.column=t,this.type=n,this.align=r,this.prev=i}function p(e,t,n){var r=e.indented;return e.context&&"statement"==e.context.type&&(r=e.context.indented),e.context=new N(r,t,n,null,e.context)}function c(e){var t=e.context.type;return")"!=t&&"]"!=t&&"}"!=t||(e.indented=e.context.indented),e.context=e.context.prev}return{name:"asn1",startState:function(){return{tokenize:null,context:new N(-2,0,"top",!1),indented:0,startOfLine:!0}},token:function(e,n){var r=n.context;if(e.sol()&&(null==r.align&&(r.align=!1),n.indented=e.indentation(),n.startOfLine=!0),e.eatSpace())return null;t=null;var i=(n.tokenize||A)(e,n);if("comment"==i)return i;if(null==r.align&&(r.align=!0),";"!=t&&":"!=t&&","!=t||"statement"!=r.type)if("{"==t)p(n,e.column(),"}");else if("["==t)p(n,e.column(),"]");else if("("==t)p(n,e.column(),")");else if("}"==t){for(;"statement"==r.type;)r=c(n);for("}"==r.type&&(r=c(n));"statement"==r.type;)r=c(n)}else t==r.type?c(n):u&&(("}"==r.type||"top"==r.type)&&";"!=t||"statement"==r.type&&"newstatement"==t)&&p(n,e.column(),"statement");else c(n);return n.startOfLine=!1,i},languageData:{indentOnInput:/^\s*[{}]$/,commentTokens:{line:"--"}}}}}}]);
+//# sourceMappingURL=2766.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/2766.index.js.map b/book/_build/html/_static/2766.index.js.map
new file mode 100644
index 0000000..8263242
--- /dev/null
+++ b/book/_build/html/_static/2766.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"2766.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/asn1.js"],"sourcesContent":["function words(str) {\n var obj = {}, words = str.split(\" \");\n for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n return obj;\n}\n\nconst defaults = {\n keywords: words(\"DEFINITIONS OBJECTS IF DERIVED INFORMATION ACTION\" +\n \" REPLY ANY NAMED CHARACTERIZED BEHAVIOUR REGISTERED\" +\n \" WITH AS IDENTIFIED CONSTRAINED BY PRESENT BEGIN\" +\n \" IMPORTS FROM UNITS SYNTAX MIN-ACCESS MAX-ACCESS\" +\n \" MINACCESS MAXACCESS REVISION STATUS DESCRIPTION\" +\n \" SEQUENCE SET COMPONENTS OF CHOICE DistinguishedName\" +\n \" ENUMERATED SIZE MODULE END INDEX AUGMENTS EXTENSIBILITY\" +\n \" IMPLIED EXPORTS\"),\n cmipVerbs: words(\"ACTIONS ADD GET NOTIFICATIONS REPLACE REMOVE\"),\n compareTypes: words(\"OPTIONAL DEFAULT MANAGED MODULE-TYPE MODULE_IDENTITY\" +\n \" MODULE-COMPLIANCE OBJECT-TYPE OBJECT-IDENTITY\" +\n \" OBJECT-COMPLIANCE MODE CONFIRMED CONDITIONAL\" +\n \" SUBORDINATE SUPERIOR CLASS TRUE FALSE NULL\" +\n \" TEXTUAL-CONVENTION\"),\n status: words(\"current deprecated mandatory obsolete\"),\n tags: words(\"APPLICATION AUTOMATIC EXPLICIT IMPLICIT PRIVATE TAGS\" +\n \" UNIVERSAL\"),\n storage: words(\"BOOLEAN INTEGER OBJECT IDENTIFIER BIT OCTET STRING\" +\n \" UTCTime InterfaceIndex IANAifType CMIP-Attribute\" +\n \" REAL PACKAGE PACKAGES IpAddress PhysAddress\" +\n \" NetworkAddress BITS BMPString TimeStamp TimeTicks\" +\n \" TruthValue RowStatus DisplayString GeneralString\" +\n \" GraphicString IA5String NumericString\" +\n \" PrintableString SnmpAdminString TeletexString\" +\n \" UTF8String VideotexString VisibleString StringStore\" +\n \" ISO646String T61String UniversalString Unsigned32\" +\n \" Integer32 Gauge Gauge32 Counter Counter32 Counter64\"),\n modifier: words(\"ATTRIBUTE ATTRIBUTES MANDATORY-GROUP MANDATORY-GROUPS\" +\n \" GROUP GROUPS ELEMENTS EQUALITY ORDERING SUBSTRINGS\" +\n \" DEFINED\"),\n accessTypes: words(\"not-accessible accessible-for-notify read-only\" +\n \" read-create read-write\"),\n multiLineStrings: true\n}\n\nexport function asn1(parserConfig) {\n var keywords = parserConfig.keywords || defaults.keywords,\n cmipVerbs = parserConfig.cmipVerbs || defaults.cmipVerbs,\n compareTypes = parserConfig.compareTypes || defaults.compareTypes,\n status = parserConfig.status || defaults.status,\n tags = parserConfig.tags || defaults.tags,\n storage = parserConfig.storage || defaults.storage,\n modifier = parserConfig.modifier || defaults.modifier,\n accessTypes = parserConfig.accessTypes|| defaults.accessTypes,\n multiLineStrings = parserConfig.multiLineStrings || defaults.multiLineStrings,\n indentStatements = parserConfig.indentStatements !== false;\n var isOperatorChar = /[\\|\\^]/;\n var curPunc;\n\n function tokenBase(stream, state) {\n var ch = stream.next();\n if (ch == '\"' || ch == \"'\") {\n state.tokenize = tokenString(ch);\n return state.tokenize(stream, state);\n }\n if (/[\\[\\]\\(\\){}:=,;]/.test(ch)) {\n curPunc = ch;\n return \"punctuation\";\n }\n if (ch == \"-\"){\n if (stream.eat(\"-\")) {\n stream.skipToEnd();\n return \"comment\";\n }\n }\n if (/\\d/.test(ch)) {\n stream.eatWhile(/[\\w\\.]/);\n return \"number\";\n }\n if (isOperatorChar.test(ch)) {\n stream.eatWhile(isOperatorChar);\n return \"operator\";\n }\n\n stream.eatWhile(/[\\w\\-]/);\n var cur = stream.current();\n if (keywords.propertyIsEnumerable(cur)) return \"keyword\";\n if (cmipVerbs.propertyIsEnumerable(cur)) return \"variableName\";\n if (compareTypes.propertyIsEnumerable(cur)) return \"atom\";\n if (status.propertyIsEnumerable(cur)) return \"comment\";\n if (tags.propertyIsEnumerable(cur)) return \"typeName\";\n if (storage.propertyIsEnumerable(cur)) return \"modifier\";\n if (modifier.propertyIsEnumerable(cur)) return \"modifier\";\n if (accessTypes.propertyIsEnumerable(cur)) return \"modifier\";\n\n return \"variableName\";\n }\n\n function tokenString(quote) {\n return function(stream, state) {\n var escaped = false, next, end = false;\n while ((next = stream.next()) != null) {\n if (next == quote && !escaped){\n var afterNext = stream.peek();\n //look if the character if the quote is like the B in '10100010'B\n if (afterNext){\n afterNext = afterNext.toLowerCase();\n if(afterNext == \"b\" || afterNext == \"h\" || afterNext == \"o\")\n stream.next();\n }\n end = true; break;\n }\n escaped = !escaped && next == \"\\\\\";\n }\n if (end || !(escaped || multiLineStrings))\n state.tokenize = null;\n return \"string\";\n };\n }\n\n function Context(indented, column, type, align, prev) {\n this.indented = indented;\n this.column = column;\n this.type = type;\n this.align = align;\n this.prev = prev;\n }\n function pushContext(state, col, type) {\n var indent = state.indented;\n if (state.context && state.context.type == \"statement\")\n indent = state.context.indented;\n return state.context = new Context(indent, col, type, null, state.context);\n }\n function popContext(state) {\n var t = state.context.type;\n if (t == \")\" || t == \"]\" || t == \"}\")\n state.indented = state.context.indented;\n return state.context = state.context.prev;\n }\n\n //Interface\n return {\n name: \"asn1\",\n startState: function() {\n return {\n tokenize: null,\n context: new Context(-2, 0, \"top\", false),\n indented: 0,\n startOfLine: true\n };\n },\n\n token: function(stream, state) {\n var ctx = state.context;\n if (stream.sol()) {\n if (ctx.align == null) ctx.align = false;\n state.indented = stream.indentation();\n state.startOfLine = true;\n }\n if (stream.eatSpace()) return null;\n curPunc = null;\n var style = (state.tokenize || tokenBase)(stream, state);\n if (style == \"comment\") return style;\n if (ctx.align == null) ctx.align = true;\n\n if ((curPunc == \";\" || curPunc == \":\" || curPunc == \",\")\n && ctx.type == \"statement\"){\n popContext(state);\n }\n else if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n else if (curPunc == \"}\") {\n while (ctx.type == \"statement\") ctx = popContext(state);\n if (ctx.type == \"}\") ctx = popContext(state);\n while (ctx.type == \"statement\") ctx = popContext(state);\n }\n else if (curPunc == ctx.type) popContext(state);\n else if (indentStatements && (((ctx.type == \"}\" || ctx.type == \"top\")\n && curPunc != ';') || (ctx.type == \"statement\"\n && curPunc == \"newstatement\")))\n pushContext(state, stream.column(), \"statement\");\n\n state.startOfLine = false;\n return style;\n },\n\n languageData: {\n indentOnInput: /^\\s*[{}]$/,\n commentTokens: {line: \"--\"}\n }\n };\n};\n"],"names":["words","str","obj","split","i","length","defaults","keywords","cmipVerbs","compareTypes","status","tags","storage","modifier","accessTypes","multiLineStrings","asn1","parserConfig","curPunc","indentStatements","isOperatorChar","tokenBase","stream","state","quote","ch","next","tokenize","escaped","end","afterNext","peek","toLowerCase","test","eat","skipToEnd","eatWhile","cur","current","propertyIsEnumerable","Context","indented","column","type","align","prev","this","pushContext","col","indent","context","popContext","t","name","startState","startOfLine","token","ctx","sol","indentation","eatSpace","style","languageData","indentOnInput","commentTokens","line"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/2795.index.js b/book/_build/html/_static/2795.index.js
new file mode 100644
index 0000000..10033cd
--- /dev/null
+++ b/book/_build/html/_static/2795.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[2795],{82795:(e,t,n)=>{function r(e){for(var t={},n=e.split(","),r=0;rh});var o,a=r("null"),l={"`":i,$:i},u=!1,s=r("abs,access,after,alias,all,and,architecture,array,assert,attribute,begin,block,body,buffer,bus,case,component,configuration,constant,disconnect,downto,else,elsif,end,end block,end case,end component,end for,end generate,end if,end loop,end process,end record,end units,entity,exit,file,for,function,generate,generic,generic map,group,guarded,if,impure,in,inertial,inout,is,label,library,linkage,literal,loop,map,mod,nand,new,next,nor,null,of,on,open,or,others,out,package,package body,port,port map,postponed,procedure,process,pure,range,record,register,reject,rem,report,return,rol,ror,select,severity,signal,sla,sll,sra,srl,subtype,then,to,transport,type,unaffected,units,until,use,variable,wait,when,while,with,xnor,xor"),c=r("architecture,entity,begin,case,port,else,elsif,end,for,function,if"),p=/[&|~>{n.r(t),n.d(t,{nsis:()=>i});const i=(0,n(74391).Q)({start:[{regex:/(?:[+-]?)(?:0x[\d,a-f]+)|(?:0o[0-7]+)|(?:0b[0,1]+)|(?:\d+.?\d*)/,token:"number"},{regex:/"(?:[^\\"]|\\.)*"?/,token:"string"},{regex:/'(?:[^\\']|\\.)*'?/,token:"string"},{regex:/`(?:[^\\`]|\\.)*`?/,token:"string"},{regex:/^\s*(?:\!(addincludedir|addplugindir|appendfile|assert|cd|define|delfile|echo|error|execute|finalize|getdllversion|gettlbversion|include|insertmacro|macro|macroend|makensis|packhdr|pragma|searchparse|searchreplace|system|tempfile|undef|uninstfinalize|verbose|warning))\b/i,token:"keyword"},{regex:/^\s*(?:\!(if(?:n?def)?|ifmacron?def|macro))\b/i,token:"keyword",indent:!0},{regex:/^\s*(?:\!(else|endif|macroend))\b/i,token:"keyword",dedent:!0},{regex:/^\s*(?:Abort|AddBrandingImage|AddSize|AllowRootDirInstall|AllowSkipFiles|AutoCloseWindow|BGFont|BGGradient|BrandingText|BringToFront|Call|CallInstDLL|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|CRCCheck|CreateDirectory|CreateFont|CreateShortCut|Delete|DeleteINISec|DeleteINIStr|DeleteRegKey|DeleteRegValue|DetailPrint|DetailsButtonText|DirText|DirVar|DirVerify|EnableWindow|EnumRegKey|EnumRegValue|Exch|Exec|ExecShell|ExecShellWait|ExecWait|ExpandEnvStrings|File|FileBufSize|FileClose|FileErrorText|FileOpen|FileRead|FileReadByte|FileReadUTF16LE|FileReadWord|FileWriteUTF16LE|FileSeek|FileWrite|FileWriteByte|FileWriteWord|FindClose|FindFirst|FindNext|FindWindow|FlushINI|GetCurInstType|GetCurrentAddress|GetDlgItem|GetDLLVersion|GetDLLVersionLocal|GetErrorLevel|GetFileTime|GetFileTimeLocal|GetFullPathName|GetFunctionAddress|GetInstDirError|GetKnownFolderPath|GetLabelAddress|GetTempFileName|GetWinVer|Goto|HideWindow|Icon|IfAbort|IfErrors|IfFileExists|IfRebootFlag|IfRtlLanguage|IfShellVarContextAll|IfSilent|InitPluginsDir|InstallButtonText|InstallColors|InstallDir|InstallDirRegKey|InstProgressFlags|InstType|InstTypeGetText|InstTypeSetText|Int64Cmp|Int64CmpU|Int64Fmt|IntCmp|IntCmpU|IntFmt|IntOp|IntPtrCmp|IntPtrCmpU|IntPtrOp|IsWindow|LangString|LicenseBkColor|LicenseData|LicenseForceSelection|LicenseLangString|LicenseText|LoadAndSetImage|LoadLanguageFile|LockWindow|LogSet|LogText|ManifestDPIAware|ManifestLongPathAware|ManifestMaxVersionTested|ManifestSupportedOS|MessageBox|MiscButtonText|Name|Nop|OutFile|Page|PageCallbacks|PEAddResource|PEDllCharacteristics|PERemoveResource|PESubsysVer|Pop|Push|Quit|ReadEnvStr|ReadINIStr|ReadRegDWORD|ReadRegStr|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|RMDir|SearchPath|SectionGetFlags|SectionGetInstTypes|SectionGetSize|SectionGetText|SectionIn|SectionSetFlags|SectionSetInstTypes|SectionSetSize|SectionSetText|SendMessage|SetAutoClose|SetBrandingImage|SetCompress|SetCompressor|SetCompressorDictSize|SetCtlColors|SetCurInstType|SetDatablockOptimize|SetDateSave|SetDetailsPrint|SetDetailsView|SetErrorLevel|SetErrors|SetFileAttributes|SetFont|SetOutPath|SetOverwrite|SetRebootFlag|SetRegView|SetShellVarContext|SetSilent|ShowInstDetails|ShowUninstDetails|ShowWindow|SilentInstall|SilentUnInstall|Sleep|SpaceTexts|StrCmp|StrCmpS|StrCpy|StrLen|SubCaption|Target|Unicode|UninstallButtonText|UninstallCaption|UninstallIcon|UninstallSubCaption|UninstallText|UninstPage|UnRegDLL|Var|VIAddVersionKey|VIFileVersion|VIProductVersion|WindowIcon|WriteINIStr|WriteRegBin|WriteRegDWORD|WriteRegExpandStr|WriteRegMultiStr|WriteRegNone|WriteRegStr|WriteUninstaller|XPStyle)\b/i,token:"keyword"},{regex:/^\s*(?:Function|PageEx|Section(?:Group)?)\b/i,token:"keyword",indent:!0},{regex:/^\s*(?:(Function|PageEx|Section(?:Group)?)End)\b/i,token:"keyword",dedent:!0},{regex:/\b(?:ARCHIVE|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_OFFLINE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY|HIDDEN|HKCC|HKCR(32|64)?|HKCU(32|64)?|HKDD|HKEY_CLASSES_ROOT|HKEY_CURRENT_CONFIG|HKEY_CURRENT_USER|HKEY_DYN_DATA|HKEY_LOCAL_MACHINE|HKEY_PERFORMANCE_DATA|HKEY_USERS|HKLM(32|64)?|HKPD|HKU|IDABORT|IDCANCEL|IDD_DIR|IDD_INST|IDD_INSTFILES|IDD_LICENSE|IDD_SELCOM|IDD_UNINST|IDD_VERIFY|IDIGNORE|IDNO|IDOK|IDRETRY|IDYES|MB_ABORTRETRYIGNORE|MB_DEFBUTTON1|MB_DEFBUTTON2|MB_DEFBUTTON3|MB_DEFBUTTON4|MB_ICONEXCLAMATION|MB_ICONINFORMATION|MB_ICONQUESTION|MB_ICONSTOP|MB_OK|MB_OKCANCEL|MB_RETRYCANCEL|MB_RIGHT|MB_RTLREADING|MB_SETFOREGROUND|MB_TOPMOST|MB_USERICON|MB_YESNO|MB_YESNOCANCEL|NORMAL|OFFLINE|READONLY|SHCTX|SHELL_CONTEXT|SW_HIDE|SW_SHOWDEFAULT|SW_SHOWMAXIMIZED|SW_SHOWMINIMIZED|SW_SHOWNORMAL|SYSTEM|TEMPORARY)\b/i,token:"atom"},{regex:/\b(?:admin|all|amd64-unicode|auto|both|bottom|bzip2|components|current|custom|directory|false|force|hide|highest|ifdiff|ifnewer|instfiles|lastused|leave|left|license|listonly|lzma|nevershow|none|normal|notset|off|on|right|show|silent|silentlog|textonly|top|true|try|un\.components|un\.custom|un\.directory|un\.instfiles|un\.license|uninstConfirm|user|Win10|Win7|Win8|WinVista|x-86-(ansi|unicode)|zlib)\b/i,token:"builtin"},{regex:/\$\{(?:And(?:If(?:Not)?|Unless)|Break|Case(?:2|3|4|5|Else)?|Continue|Default|Do(?:Until|While)?|Else(?:If(?:Not)?|Unless)?|End(?:If|Select|Switch)|Exit(?:Do|For|While)|For(?:Each)?|If(?:Cmd|Not(?:Then)?|Then)?|Loop(?:Until|While)?|Or(?:If(?:Not)?|Unless)|Select|Switch|Unless|While)\}/i,token:"variable-2",indent:!0},{regex:/\$\{(?:BannerTrimPath|DirState|DriveSpace|Get(BaseName|Drives|ExeName|ExePath|FileAttributes|FileExt|FileName|FileVersion|Options|OptionsS|Parameters|Parent|Root|Size|Time)|Locate|RefreshShellIcons)\}/i,token:"variable-2",dedent:!0},{regex:/\$\{(?:Memento(?:Section(?:Done|End|Restore|Save)?|UnselectedSection))\}/i,token:"variable-2",dedent:!0},{regex:/\$\{(?:Config(?:Read|ReadS|Write|WriteS)|File(?:Join|ReadFromEnd|Recode)|Line(?:Find|Read|Sum)|Text(?:Compare|CompareS)|TrimNewLines)\}/i,token:"variable-2",dedent:!0},{regex:/\$\{(?:(?:At(?:Least|Most)|Is)(?:ServicePack|Win(?:7|8|10|95|98|200(?:0|3|8(?:R2)?)|ME|NT4|Vista|XP))|Is(?:NT|Server))\}/i,token:"variable",dedent:!0},{regex:/\$\{(?:StrFilterS?|Version(?:Compare|Convert)|Word(?:AddS?|Find(?:(?:2|3)X)?S?|InsertS?|ReplaceS?))\}/i,token:"keyword",dedent:!0},{regex:/\$\{(?:RunningX64)\}/i,token:"variable",dedent:!0},{regex:/\$\{(?:Disable|Enable)X64FSRedirection\}/i,token:"keyword",dedent:!0},{regex:/(#|;).*/,token:"comment"},{regex:/\/\*/,token:"comment",next:"comment"},{regex:/[-+\/*=<>!]+/,token:"operator"},{regex:/\$\w[\w\.]*/,token:"variable"},{regex:/\${[\!\w\.:-]+}/,token:"variableName.constant"},{regex:/\$\([\!\w\.:-]+\)/,token:"atom"}],comment:[{regex:/.*?\*\//,token:"comment",next:"start"},{regex:/.*/,token:"comment"}],languageData:{name:"nsis",indentOnInput:/^\s*((Function|PageEx|Section|Section(Group)?)End|(\!(endif|macroend))|\$\{(End(If|Unless|While)|Loop(Until)|Next)\})$/i,commentTokens:{line:"#",block:{open:"/*",close:"*/"}}}})},74391:(e,t,n)=>{function i(e){r(e,"start");var t={},n=e.languageData||{},i=!1;for(var l in e)if(l!=n&&e.hasOwnProperty(l))for(var d=t[l]=[],S=e[l],c=0;c2&&a.token&&"string"!=typeof a.token){n.pending=[];for(var d=2;d-1)return null;var r=n.indent.length-1,o=e[n.state];e:for(;;){for(var a=0;ai})}}]);
+//# sourceMappingURL=2870.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/2870.index.js.map b/book/_build/html/_static/2870.index.js.map
new file mode 100644
index 0000000..4fb8066
--- /dev/null
+++ b/book/_build/html/_static/2870.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"2870.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/nsis.js","webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/simple-mode.js"],"sourcesContent":["import {simpleMode} from \"./simple-mode.js\"\nexport const nsis = simpleMode({\n start:[\n // Numbers\n {regex: /(?:[+-]?)(?:0x[\\d,a-f]+)|(?:0o[0-7]+)|(?:0b[0,1]+)|(?:\\d+.?\\d*)/, token: \"number\"},\n\n // Strings\n { regex: /\"(?:[^\\\\\"]|\\\\.)*\"?/, token: \"string\" },\n { regex: /'(?:[^\\\\']|\\\\.)*'?/, token: \"string\" },\n { regex: /`(?:[^\\\\`]|\\\\.)*`?/, token: \"string\" },\n\n // Compile Time Commands\n {regex: /^\\s*(?:\\!(addincludedir|addplugindir|appendfile|assert|cd|define|delfile|echo|error|execute|finalize|getdllversion|gettlbversion|include|insertmacro|macro|macroend|makensis|packhdr|pragma|searchparse|searchreplace|system|tempfile|undef|uninstfinalize|verbose|warning))\\b/i, token: \"keyword\"},\n\n // Conditional Compilation\n {regex: /^\\s*(?:\\!(if(?:n?def)?|ifmacron?def|macro))\\b/i, token: \"keyword\", indent: true},\n {regex: /^\\s*(?:\\!(else|endif|macroend))\\b/i, token: \"keyword\", dedent: true},\n\n // Runtime Commands\n {regex: /^\\s*(?:Abort|AddBrandingImage|AddSize|AllowRootDirInstall|AllowSkipFiles|AutoCloseWindow|BGFont|BGGradient|BrandingText|BringToFront|Call|CallInstDLL|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|CRCCheck|CreateDirectory|CreateFont|CreateShortCut|Delete|DeleteINISec|DeleteINIStr|DeleteRegKey|DeleteRegValue|DetailPrint|DetailsButtonText|DirText|DirVar|DirVerify|EnableWindow|EnumRegKey|EnumRegValue|Exch|Exec|ExecShell|ExecShellWait|ExecWait|ExpandEnvStrings|File|FileBufSize|FileClose|FileErrorText|FileOpen|FileRead|FileReadByte|FileReadUTF16LE|FileReadWord|FileWriteUTF16LE|FileSeek|FileWrite|FileWriteByte|FileWriteWord|FindClose|FindFirst|FindNext|FindWindow|FlushINI|GetCurInstType|GetCurrentAddress|GetDlgItem|GetDLLVersion|GetDLLVersionLocal|GetErrorLevel|GetFileTime|GetFileTimeLocal|GetFullPathName|GetFunctionAddress|GetInstDirError|GetKnownFolderPath|GetLabelAddress|GetTempFileName|GetWinVer|Goto|HideWindow|Icon|IfAbort|IfErrors|IfFileExists|IfRebootFlag|IfRtlLanguage|IfShellVarContextAll|IfSilent|InitPluginsDir|InstallButtonText|InstallColors|InstallDir|InstallDirRegKey|InstProgressFlags|InstType|InstTypeGetText|InstTypeSetText|Int64Cmp|Int64CmpU|Int64Fmt|IntCmp|IntCmpU|IntFmt|IntOp|IntPtrCmp|IntPtrCmpU|IntPtrOp|IsWindow|LangString|LicenseBkColor|LicenseData|LicenseForceSelection|LicenseLangString|LicenseText|LoadAndSetImage|LoadLanguageFile|LockWindow|LogSet|LogText|ManifestDPIAware|ManifestLongPathAware|ManifestMaxVersionTested|ManifestSupportedOS|MessageBox|MiscButtonText|Name|Nop|OutFile|Page|PageCallbacks|PEAddResource|PEDllCharacteristics|PERemoveResource|PESubsysVer|Pop|Push|Quit|ReadEnvStr|ReadINIStr|ReadRegDWORD|ReadRegStr|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|RMDir|SearchPath|SectionGetFlags|SectionGetInstTypes|SectionGetSize|SectionGetText|SectionIn|SectionSetFlags|SectionSetInstTypes|SectionSetSize|SectionSetText|SendMessage|SetAutoClose|SetBrandingImage|SetCompress|SetCompressor|SetCompressorDictSize|SetCtlColors|SetCurInstType|SetDatablockOptimize|SetDateSave|SetDetailsPrint|SetDetailsView|SetErrorLevel|SetErrors|SetFileAttributes|SetFont|SetOutPath|SetOverwrite|SetRebootFlag|SetRegView|SetShellVarContext|SetSilent|ShowInstDetails|ShowUninstDetails|ShowWindow|SilentInstall|SilentUnInstall|Sleep|SpaceTexts|StrCmp|StrCmpS|StrCpy|StrLen|SubCaption|Target|Unicode|UninstallButtonText|UninstallCaption|UninstallIcon|UninstallSubCaption|UninstallText|UninstPage|UnRegDLL|Var|VIAddVersionKey|VIFileVersion|VIProductVersion|WindowIcon|WriteINIStr|WriteRegBin|WriteRegDWORD|WriteRegExpandStr|WriteRegMultiStr|WriteRegNone|WriteRegStr|WriteUninstaller|XPStyle)\\b/i, token: \"keyword\"},\n {regex: /^\\s*(?:Function|PageEx|Section(?:Group)?)\\b/i, token: \"keyword\", indent: true},\n {regex: /^\\s*(?:(Function|PageEx|Section(?:Group)?)End)\\b/i, token: \"keyword\", dedent: true},\n\n // Command Options\n {regex: /\\b(?:ARCHIVE|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_OFFLINE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY|HIDDEN|HKCC|HKCR(32|64)?|HKCU(32|64)?|HKDD|HKEY_CLASSES_ROOT|HKEY_CURRENT_CONFIG|HKEY_CURRENT_USER|HKEY_DYN_DATA|HKEY_LOCAL_MACHINE|HKEY_PERFORMANCE_DATA|HKEY_USERS|HKLM(32|64)?|HKPD|HKU|IDABORT|IDCANCEL|IDD_DIR|IDD_INST|IDD_INSTFILES|IDD_LICENSE|IDD_SELCOM|IDD_UNINST|IDD_VERIFY|IDIGNORE|IDNO|IDOK|IDRETRY|IDYES|MB_ABORTRETRYIGNORE|MB_DEFBUTTON1|MB_DEFBUTTON2|MB_DEFBUTTON3|MB_DEFBUTTON4|MB_ICONEXCLAMATION|MB_ICONINFORMATION|MB_ICONQUESTION|MB_ICONSTOP|MB_OK|MB_OKCANCEL|MB_RETRYCANCEL|MB_RIGHT|MB_RTLREADING|MB_SETFOREGROUND|MB_TOPMOST|MB_USERICON|MB_YESNO|MB_YESNOCANCEL|NORMAL|OFFLINE|READONLY|SHCTX|SHELL_CONTEXT|SW_HIDE|SW_SHOWDEFAULT|SW_SHOWMAXIMIZED|SW_SHOWMINIMIZED|SW_SHOWNORMAL|SYSTEM|TEMPORARY)\\b/i, token: \"atom\"},\n {regex: /\\b(?:admin|all|amd64-unicode|auto|both|bottom|bzip2|components|current|custom|directory|false|force|hide|highest|ifdiff|ifnewer|instfiles|lastused|leave|left|license|listonly|lzma|nevershow|none|normal|notset|off|on|right|show|silent|silentlog|textonly|top|true|try|un\\.components|un\\.custom|un\\.directory|un\\.instfiles|un\\.license|uninstConfirm|user|Win10|Win7|Win8|WinVista|x-86-(ansi|unicode)|zlib)\\b/i, token: \"builtin\"},\n\n // LogicLib.nsh\n {regex: /\\$\\{(?:And(?:If(?:Not)?|Unless)|Break|Case(?:2|3|4|5|Else)?|Continue|Default|Do(?:Until|While)?|Else(?:If(?:Not)?|Unless)?|End(?:If|Select|Switch)|Exit(?:Do|For|While)|For(?:Each)?|If(?:Cmd|Not(?:Then)?|Then)?|Loop(?:Until|While)?|Or(?:If(?:Not)?|Unless)|Select|Switch|Unless|While)\\}/i, token: \"variable-2\", indent: true},\n\n // FileFunc.nsh\n {regex: /\\$\\{(?:BannerTrimPath|DirState|DriveSpace|Get(BaseName|Drives|ExeName|ExePath|FileAttributes|FileExt|FileName|FileVersion|Options|OptionsS|Parameters|Parent|Root|Size|Time)|Locate|RefreshShellIcons)\\}/i, token: \"variable-2\", dedent: true},\n\n // Memento.nsh\n {regex: /\\$\\{(?:Memento(?:Section(?:Done|End|Restore|Save)?|UnselectedSection))\\}/i, token: \"variable-2\", dedent: true},\n\n // TextFunc.nsh\n {regex: /\\$\\{(?:Config(?:Read|ReadS|Write|WriteS)|File(?:Join|ReadFromEnd|Recode)|Line(?:Find|Read|Sum)|Text(?:Compare|CompareS)|TrimNewLines)\\}/i, token: \"variable-2\", dedent: true},\n\n // WinVer.nsh\n {regex: /\\$\\{(?:(?:At(?:Least|Most)|Is)(?:ServicePack|Win(?:7|8|10|95|98|200(?:0|3|8(?:R2)?)|ME|NT4|Vista|XP))|Is(?:NT|Server))\\}/i, token: \"variable\", dedent: true},\n\n // WordFunc.nsh\n {regex: /\\$\\{(?:StrFilterS?|Version(?:Compare|Convert)|Word(?:AddS?|Find(?:(?:2|3)X)?S?|InsertS?|ReplaceS?))\\}/i, token: \"keyword\", dedent: true},\n\n // x64.nsh\n {regex: /\\$\\{(?:RunningX64)\\}/i, token: \"variable\", dedent: true},\n {regex: /\\$\\{(?:Disable|Enable)X64FSRedirection\\}/i, token: \"keyword\", dedent: true},\n\n // Line Comment\n {regex: /(#|;).*/, token: \"comment\"},\n\n // Block Comment\n {regex: /\\/\\*/, token: \"comment\", next: \"comment\"},\n\n // Operator\n {regex: /[-+\\/*=<>!]+/, token: \"operator\"},\n\n // Variable\n {regex: /\\$\\w[\\w\\.]*/, token: \"variable\"},\n\n // Constant\n {regex: /\\${[\\!\\w\\.:-]+}/, token: \"variableName.constant\"},\n\n // Language String\n {regex: /\\$\\([\\!\\w\\.:-]+\\)/, token: \"atom\"}\n ],\n comment: [\n {regex: /.*?\\*\\//, token: \"comment\", next: \"start\"},\n {regex: /.*/, token: \"comment\"}\n ],\n languageData: {\n name: \"nsis\",\n indentOnInput: /^\\s*((Function|PageEx|Section|Section(Group)?)End|(\\!(endif|macroend))|\\$\\{(End(If|Unless|While)|Loop(Until)|Next)\\})$/i,\n commentTokens: {line: \"#\", block: {open: \"/*\", close: \"*/\"}}\n }\n});\n\n","export function simpleMode(states) {\n ensureState(states, \"start\");\n var states_ = {}, meta = states.languageData || {}, hasIndentation = false;\n for (var state in states) if (state != meta && states.hasOwnProperty(state)) {\n var list = states_[state] = [], orig = states[state];\n for (var i = 0; i < orig.length; i++) {\n var data = orig[i];\n list.push(new Rule(data, states));\n if (data.indent || data.dedent) hasIndentation = true;\n }\n }\n return {\n name: meta.name,\n startState: function() {\n return {state: \"start\", pending: null, indent: hasIndentation ? [] : null};\n },\n copyState: function(state) {\n var s = {state: state.state, pending: state.pending, indent: state.indent && state.indent.slice(0)};\n if (state.stack)\n s.stack = state.stack.slice(0);\n return s;\n },\n token: tokenFunction(states_),\n indent: indentFunction(states_, meta),\n languageData: meta\n }\n};\n\nfunction ensureState(states, name) {\n if (!states.hasOwnProperty(name))\n throw new Error(\"Undefined state \" + name + \" in simple mode\");\n}\n\nfunction toRegex(val, caret) {\n if (!val) return /(?:)/;\n var flags = \"\";\n if (val instanceof RegExp) {\n if (val.ignoreCase) flags = \"i\";\n val = val.source;\n } else {\n val = String(val);\n }\n return new RegExp((caret === false ? \"\" : \"^\") + \"(?:\" + val + \")\", flags);\n}\n\nfunction asToken(val) {\n if (!val) return null;\n if (val.apply) return val\n if (typeof val == \"string\") return val.replace(/\\./g, \" \");\n var result = [];\n for (var i = 0; i < val.length; i++)\n result.push(val[i] && val[i].replace(/\\./g, \" \"));\n return result;\n}\n\nfunction Rule(data, states) {\n if (data.next || data.push) ensureState(states, data.next || data.push);\n this.regex = toRegex(data.regex);\n this.token = asToken(data.token);\n this.data = data;\n}\n\nfunction tokenFunction(states) {\n return function(stream, state) {\n if (state.pending) {\n var pend = state.pending.shift();\n if (state.pending.length == 0) state.pending = null;\n stream.pos += pend.text.length;\n return pend.token;\n }\n\n var curState = states[state.state];\n for (var i = 0; i < curState.length; i++) {\n var rule = curState[i];\n var matches = (!rule.data.sol || stream.sol()) && stream.match(rule.regex);\n if (matches) {\n if (rule.data.next) {\n state.state = rule.data.next;\n } else if (rule.data.push) {\n (state.stack || (state.stack = [])).push(state.state);\n state.state = rule.data.push;\n } else if (rule.data.pop && state.stack && state.stack.length) {\n state.state = state.stack.pop();\n }\n\n if (rule.data.indent)\n state.indent.push(stream.indentation() + stream.indentUnit);\n if (rule.data.dedent)\n state.indent.pop();\n var token = rule.token\n if (token && token.apply) token = token(matches)\n if (matches.length > 2 && rule.token && typeof rule.token != \"string\") {\n state.pending = [];\n for (var j = 2; j < matches.length; j++)\n if (matches[j])\n state.pending.push({text: matches[j], token: rule.token[j - 1]});\n stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));\n return token[0];\n } else if (token && token.join) {\n return token[0];\n } else {\n return token;\n }\n }\n }\n stream.next();\n return null;\n };\n}\n\nfunction indentFunction(states, meta) {\n return function(state, textAfter) {\n if (state.indent == null || meta.dontIndentStates && meta.doneIndentState.indexOf(state.state) > -1)\n return null\n\n var pos = state.indent.length - 1, rules = states[state.state];\n scan: for (;;) {\n for (var i = 0; i < rules.length; i++) {\n var rule = rules[i];\n if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {\n var m = rule.regex.exec(textAfter);\n if (m && m[0]) {\n pos--;\n if (rule.next || rule.push) rules = states[rule.next || rule.push];\n textAfter = textAfter.slice(m[0].length);\n continue scan;\n }\n }\n }\n break;\n }\n return pos < 0 ? 0 : state.indent[pos];\n };\n}\n"],"names":["nsis","start","regex","token","indent","dedent","next","comment","languageData","name","indentOnInput","commentTokens","line","block","open","close","simpleMode","states","ensureState","states_","meta","hasIndentation","state","hasOwnProperty","list","orig","i","length","data","push","Rule","startState","pending","copyState","s","slice","stack","tokenFunction","indentFunction","Error","this","val","caret","flags","RegExp","ignoreCase","source","String","toRegex","apply","replace","result","asToken","stream","pend","shift","pos","text","curState","rule","matches","sol","match","pop","indentation","indentUnit","j","backUp","join","textAfter","dontIndentStates","doneIndentState","indexOf","rules","scan","dedentIfLineStart","m","exec"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/296.thebe-lite.min.js b/book/_build/html/_static/296.thebe-lite.min.js
new file mode 100644
index 0000000..f4fc763
--- /dev/null
+++ b/book/_build/html/_static/296.thebe-lite.min.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe_lite=self.webpackChunkthebe_lite||[]).push([[296],{3296:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{O:()=>Yt});var ni=Object.create,Me=Object.defineProperty,ai=Object.getOwnPropertyDescriptor,oi=Object.getOwnPropertyNames,si=Object.getPrototypeOf,ri=Object.prototype.hasOwnProperty,ce=(t,e)=>()=>(t&&(e=t(t=0)),e),F=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),li=(t,e)=>{for(var i in e)Me(t,i,{get:e[i],enumerable:!0})},ci=(t,e,i,a)=>{if(e&&"object"==typeof e||"function"==typeof e)for(let n of oi(e))!ri.call(t,n)&&n!==i&&Me(t,n,{get:()=>e[n],enumerable:!(a=ai(e,n))||a.enumerable});return t},se=(t,e,i)=>(i=null!=t?ni(si(t)):{},ci(!e&&t&&t.__esModule?i:Me(i,"default",{value:t,enumerable:!0}),t)),Ye=F(((t,e)=>{var i,a;i=t,a=function(t){function e(t,e){let i=0;for(let a of t)if(!1===e(a,i++))return!1;return!0}var i;t.ArrayExt=void 0,function(t){function e(t,e,i=0,a=-1){let n,o=t.length;if(0===o)return-1;i=i<0?Math.max(0,i+o):Math.min(i,o-1),n=(a=a<0?Math.max(0,a+o):Math.min(a,o-1))=i)return;let a=t[e];for(let a=e+1;a0;){let a=r>>1,n=l+a;i(t[n],e)<0?(l=n+1,r-=a+1):r=a}return l},t.upperBound=function(t,e,i,a=0,n=-1){let o=t.length;if(0===o)return 0;let l=a=a<0?Math.max(0,a+o):Math.min(a,o-1),r=(n=n<0?Math.max(0,n+o):Math.min(n,o-1))-a+1;for(;r>0;){let a=r>>1,n=l+a;i(t[n],e)>0?r=a:(l=n+1,r-=a+1)}return l},t.shallowEqual=function(t,e,i){if(t===e)return!0;if(t.length!==e.length)return!1;for(let a=0,n=t.length;a=l&&(i=n<0?l-1:l),void 0===a?a=n<0?-1:l:a<0?a=Math.max(a+l,n<0?-1:0):a>=l&&(a=n<0?l-1:l),o=n<0&&a>=i||n>0&&i>=a?0:n<0?Math.floor((a-i+1)/n+1):Math.floor((a-i-1)/n+1);let r=[];for(let e=0;e=(a=a<0?Math.max(0,a+n):Math.min(a,n-1)))return;let l=a-i+1;if(e>0?e%=l:e<0&&(e=(e%l+l)%l),0===e)return;let r=i+e;o(t,i,r-1),o(t,r,a),o(t,i,a)},t.fill=function(t,e,i=0,a=-1){let n,o=t.length;if(0!==o){i=i<0?Math.max(0,i+o):Math.min(i,o-1),n=(a=a<0?Math.max(0,a+o):Math.min(a,o-1))e;--i)t[i]=t[i-1];t[e]=i},t.removeAt=l,t.removeFirstOf=function(t,i,a=0,n=-1){let o=e(t,i,a,n);return-1!==o&&l(t,o),o},t.removeLastOf=function(t,e,a=-1,n=0){let o=i(t,e,a,n);return-1!==o&&l(t,o),o},t.removeAllOf=function(t,e,i=0,a=-1){let n=t.length;if(0===n)return 0;i=i<0?Math.max(0,i+n):Math.min(i,n-1),a=a<0?Math.max(0,a+n):Math.min(a,n-1);let o=0;for(let l=0;l=i&&l<=a&&t[l]===e||a=i)&&t[l]===e?o++:o>0&&(t[l-o]=t[l]);return o>0&&(t.length=n-o),o},t.removeFirstWhere=function(t,e,i=0,n=-1){let o,r=a(t,e,i,n);return-1!==r&&(o=l(t,r)),{index:r,value:o}},t.removeLastWhere=function(t,e,i=-1,a=0){let o,r=n(t,e,i,a);return-1!==r&&(o=l(t,r)),{index:r,value:o}},t.removeAllWhere=function(t,e,i=0,a=-1){let n=t.length;if(0===n)return 0;i=i<0?Math.max(0,i+n):Math.min(i,n-1),a=a<0?Math.max(0,a+n):Math.min(a,n-1);let o=0;for(let l=0;l=i&&l<=a&&e(t[l],l)||a=i)&&e(t[l],l)?o++:o>0&&(t[l-o]=t[l]);return o>0&&(t.length=n-o),o}}(t.ArrayExt||(t.ArrayExt={})),(i||(i={})).rangeLength=function(t,e,i){return 0===i?1/0:t>e&&i>0||te?1:0}}(t.StringExt||(t.StringExt={})),t.chain=function*(...t){for(let e of t)yield*e},t.each=function(t,e){let i=0;for(let a of t)if(!1===e(a,i++))return},t.empty=function*(){},t.enumerate=function*(t,e=0){for(let i of t)yield[e++,i]},t.every=e,t.filter=function*(t,e){let i=0;for(let a of t)e(a,i++)&&(yield a)},t.find=function(t,e){let i=0;for(let a of t)if(e(a,i++))return a},t.findIndex=function(t,e){let i=0;for(let a of t)if(e(a,i++))return i-1;return-1},t.map=function*(t,e){let i=0;for(let a of t)yield e(a,i++)},t.max=function(t,e){let i;for(let a of t)void 0!==i?e(a,i)>0&&(i=a):i=a;return i},t.min=function(t,e){let i;for(let a of t)void 0!==i?e(a,i)<0&&(i=a):i=a;return i},t.minmax=function(t,e){let i,a,n=!0;for(let o of t)n?(i=o,a=o,n=!1):e(o,i)<0?i=o:e(o,a)>0&&(a=o);return n?void 0:[i,a]},t.once=function*(t){yield t},t.range=function*(t,e,a){void 0===e?(e=t,t=0,a=1):void 0===a&&(a=1);let n=i.rangeLength(t,e,a);for(let e=0;e-1;e--)yield t[e]},t.some=function(t,e){let i=0;for(let a of t)if(e(a,i++))return!0;return!1},t.stride=function*(t,e){let i=0;for(let a of t)i++%e==0&&(yield a)},t.take=function*(t,e){if(e<1)return;let i,a=t[Symbol.iterator]();for(;0t[Symbol.iterator]())),a=i.map((t=>t.next()));for(;e(a,(t=>!t.done));a=i.map((t=>t.next())))yield a.map((t=>t.value))}},"object"==typeof t&&void 0!==e?a(t):"function"==typeof define&&__webpack_require__.amdO?define(["exports"],a):a((i="undefined"!=typeof globalThis?globalThis:i||self).lumino_algorithm={})})),pe=F(((t,e)=>{var i,a;i=t,a=function(t){function e(t){let e=0;for(let i=0,a=t.length;i>>0),t[i]=255&e,e>>>=8}t.JSONExt=void 0,function(t){function e(t){return null===t||"boolean"==typeof t||"number"==typeof t||"string"==typeof t}function i(t){return Array.isArray(t)}t.emptyObject=Object.freeze({}),t.emptyArray=Object.freeze([]),t.isPrimitive=e,t.isArray=i,t.isObject=function(t){return!e(t)&&!i(t)},t.deepEqual=function t(a,n){if(a===n)return!0;if(e(a)||e(n))return!1;let o=i(a),l=i(n);return o===l&&(o&&l?function(e,i){if(e===i)return!0;if(e.length!==i.length)return!1;for(let a=0,n=e.length;a{let t="undefined"!=typeof window&&(window.crypto||window.msCrypto)||null;return t&&"function"==typeof t.getRandomValues?function(e){return t.getRandomValues(e)}:e})(),t.UUID=void 0,(t.UUID||(t.UUID={})).uuid4=function(t){let e=new Uint8Array(16),i=new Array(256);for(let t=0;t<16;++t)i[t]="0"+t.toString(16);for(let t=16;t<256;++t)i[t]=t.toString(16);return function(){return t(e),e[6]=64|15&e[6],e[8]=128|63&e[8],i[e[0]]+i[e[1]]+i[e[2]]+i[e[3]]+"-"+i[e[4]]+i[e[5]]+"-"+i[e[6]]+i[e[7]]+"-"+i[e[8]]+i[e[9]]+"-"+i[e[10]]+i[e[11]]+i[e[12]]+i[e[13]]+i[e[14]]+i[e[15]]}}(t.Random.getRandomValues),t.MimeData=class{constructor(){this._types=[],this._values=[]}types(){return this._types.slice()}hasData(t){return-1!==this._types.indexOf(t)}getData(t){let e=this._types.indexOf(t);return-1!==e?this._values[e]:void 0}setData(t,e){this.clearData(t),this._types.push(t),this._values.push(e)}clearData(t){let e=this._types.indexOf(t);-1!==e&&(this._types.splice(e,1),this._values.splice(e,1))}clear(){this._types.length=0,this._values.length=0}},t.PromiseDelegate=class{constructor(){this.promise=new Promise(((t,e)=>{this._resolve=t,this._reject=e}))}resolve(t){(0,this._resolve)(t)}reject(t){(0,this._reject)(t)}},t.Token=class{constructor(t,e){this.name=t,this.description=null!=e?e:"",this._tokenStructuralPropertyT=null}}},"object"==typeof t&&void 0!==e?a(t):"function"==typeof define&&__webpack_require__.amdO?define(["exports"],a):a((i="undefined"!=typeof globalThis?globalThis:i||self).lumino_coreutils={})})),Xe=F(((t,e)=>{var i,a;i=t,a=function(t,e,i){class a{constructor(t){this.sender=t}connect(t,e){return o.connect(this,t,e)}disconnect(t,e){return o.disconnect(this,t,e)}emit(t){o.emit(this,t)}}var n,o;(n=a||(a={})).disconnectBetween=function(t,e){o.disconnectBetween(t,e)},n.disconnectSender=function(t){o.disconnectSender(t)},n.disconnectReceiver=function(t){o.disconnectReceiver(t)},n.disconnectAll=function(t){o.disconnectAll(t)},n.clearData=function(t){o.disconnectAll(t)},n.getExceptionHandler=function(){return o.exceptionHandler},n.setExceptionHandler=function(t){let e=o.exceptionHandler;return o.exceptionHandler=t,e};class l extends a{constructor(){super(...arguments),this._pending=new i.PromiseDelegate}async*[Symbol.asyncIterator](){let t=this._pending;for(;;)try{let{args:e,next:i}=await t.promise;t=i,yield e}catch{return}}emit(t){let e=this._pending,a=this._pending=new i.PromiseDelegate;e.resolve({args:t,next:a}),super.emit(t)}stop(){this._pending.promise.catch((()=>{})),this._pending.reject("stop"),this._pending=new i.PromiseDelegate}}(function(t){function i(t){let e=n.get(t);if(e&&0!==e.length){for(let t of e){if(!t.signal)continue;let e=t.thisArg||t.slot;t.signal=null,c(o.get(e))}c(e)}}function a(t){let e=o.get(t);if(e&&0!==e.length){for(let t of e){if(!t.signal)continue;let e=t.signal.sender;t.signal=null,c(n.get(e))}c(e)}}t.exceptionHandler=t=>{console.error(t)},t.connect=function(t,e,i){i=i||void 0;let a=n.get(t.sender);if(a||(a=[],n.set(t.sender,a)),p(a,t,e,i))return!1;let l=i||e,r=o.get(l);r||(r=[],o.set(l,r));let s={signal:t,slot:e,thisArg:i};return a.push(s),r.push(s),!0},t.disconnect=function(t,e,i){i=i||void 0;let a=n.get(t.sender);if(!a||0===a.length)return!1;let l=p(a,t,e,i);if(!l)return!1;let r=i||e,s=o.get(r);return l.signal=null,c(a),c(s),!0},t.disconnectBetween=function(t,e){let i=n.get(t);if(!i||0===i.length)return;let a=o.get(e);if(a&&0!==a.length){for(let e of a)e.signal&&e.signal.sender===t&&(e.signal=null);c(i),c(a)}},t.disconnectSender=i,t.disconnectReceiver=a,t.disconnectAll=function(t){i(t),a(t)},t.emit=function(t,e){let i=n.get(t.sender);if(i&&0!==i.length)for(let a=0,n=i.length;at.signal===i&&t.slot===a&&t.thisArg===n))}function s(e,i){let{signal:a,slot:n,thisArg:o}=e;try{n.call(o,a.sender,i)}catch(e){t.exceptionHandler(e)}}function c(t){0===l.size&&r(d),l.add(t)}function d(){l.forEach(m),l.clear()}function m(t){e.ArrayExt.removeAllWhere(t,u)}function u(t){return null===t.signal}})(o||(o={})),t.Signal=a,t.Stream=l},"object"==typeof t&&void 0!==e?a(t,Ye(),pe()):"function"==typeof define&&__webpack_require__.amdO?define(["exports","@lumino/algorithm","@lumino/coreutils"],a):a((i="undefined"!=typeof globalThis?globalThis:i||self).lumino_signaling={},i.lumino_algorithm,i.lumino_coreutils)})),et=F((t=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ActivityMonitor=void 0;var e=Xe();t.ActivityMonitor=class{constructor(t){this._timer=-1,this._timeout=-1,this._isDisposed=!1,this._activityStopped=new e.Signal(this),t.signal.connect(this._onSignalFired,this),this._timeout=t.timeout||1e3}get activityStopped(){return this._activityStopped}get timeout(){return this._timeout}set timeout(t){this._timeout=t}get isDisposed(){return this._isDisposed}dispose(){this._isDisposed||(this._isDisposed=!0,e.Signal.clearData(this))}_onSignalFired(t,e){clearTimeout(this._timer),this._sender=t,this._args=e,this._timer=setTimeout((()=>{this._activityStopped.emit({sender:this._sender,args:this._args})}),this._timeout)}}})),it=F((t=>{Object.defineProperty(t,"__esModule",{value:!0})})),nt=F((t=>{Object.defineProperty(t,"__esModule",{value:!0}),t.MarkdownCodeBlocks=void 0,function(t){t.CODE_BLOCK_MARKER="```";let e=[".markdown",".mdown",".mkdn",".md",".mkd",".mdwn",".mdtxt",".mdtext",".text",".txt",".Rmd"];class i{constructor(t){this.startLine=t,this.code="",this.endLine=-1}}t.MarkdownCodeBlock=i,t.isMarkdown=function(t){return e.indexOf(t)>-1},t.findMarkdownCodeBlocks=function(e){if(!e||""===e)return[];let a=e.split("\n"),n=[],o=null;for(let e=0;e{function i(t){return!("number"!=typeof t&&!/^0x[0-9a-f]+$/i.test(t))||/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(t)}function a(t,e){return"constructor"===e&&"function"==typeof t[e]||"__proto__"===e}e.exports=function(t,e){e||(e={});var n={bools:{},strings:{},unknownFn:null};"function"==typeof e.unknown&&(n.unknownFn=e.unknown),"boolean"==typeof e.boolean&&e.boolean?n.allBools=!0:[].concat(e.boolean).filter(Boolean).forEach((function(t){n.bools[t]=!0}));var o={};function l(t){return o[t].some((function(t){return n.bools[t]}))}Object.keys(e.alias||{}).forEach((function(t){o[t]=[].concat(e.alias[t]),o[t].forEach((function(e){o[e]=[t].concat(o[t].filter((function(t){return e!==t})))}))})),[].concat(e.string).filter(Boolean).forEach((function(t){n.strings[t]=!0,o[t]&&[].concat(o[t]).forEach((function(t){n.strings[t]=!0}))}));var r=e.default||{},p={_:[]};function s(t,e,i){for(var o=t,l=0;l{function i(t){if("string"!=typeof t)throw new TypeError("Path must be a string. Received "+JSON.stringify(t))}function a(t,e){for(var i,a="",n=0,o=-1,l=0,r=0;r<=t.length;++r){if(r2){var p=a.lastIndexOf("/");if(p!==a.length-1){-1===p?(a="",n=0):n=(a=a.slice(0,p)).length-1-a.lastIndexOf("/"),o=r,l=0;continue}}else if(2===a.length||1===a.length){a="",n=0,o=r,l=0;continue}e&&(a.length>0?a+="/..":a="..",n=2)}else a.length>0?a+="/"+t.slice(o+1,r):a=t.slice(o+1,r),n=r-o-1;o=r,l=0}else 46===i&&-1!==l?++l:l=-1}return a}var n={resolve:function(){for(var t,e="",n=!1,o=arguments.length-1;o>=-1&&!n;o--){var l;o>=0?l=arguments[o]:(void 0===t&&(t=process.cwd()),l=t),i(l),0!==l.length&&(e=l+"/"+e,n=47===l.charCodeAt(0))}return e=a(e,!n),n?e.length>0?"/"+e:"/":e.length>0?e:"."},normalize:function(t){if(i(t),0===t.length)return".";var e=47===t.charCodeAt(0),n=47===t.charCodeAt(t.length-1);return 0===(t=a(t,!e)).length&&!e&&(t="."),t.length>0&&n&&(t+="/"),e?"/"+t:t},isAbsolute:function(t){return i(t),t.length>0&&47===t.charCodeAt(0)},join:function(){if(0===arguments.length)return".";for(var t,e=0;e0&&(void 0===t?t=a:t+="/"+a)}return void 0===t?".":n.normalize(t)},relative:function(t,e){if(i(t),i(e),t===e||(t=n.resolve(t))===(e=n.resolve(e)))return"";for(var a=1;as){if(47===e.charCodeAt(r+d))return e.slice(r+d+1);if(0===d)return e.slice(r+d)}else l>s&&(47===t.charCodeAt(a+d)?c=d:0===d&&(c=0));break}var m=t.charCodeAt(a+d);if(m!==e.charCodeAt(r+d))break;47===m&&(c=d)}var u="";for(d=a+c+1;d<=o;++d)(d===o||47===t.charCodeAt(d))&&(0===u.length?u+="..":u+="/..");return u.length>0?u+e.slice(r+c):(r+=c,47===e.charCodeAt(r)&&++r,e.slice(r))},_makeLong:function(t){return t},dirname:function(t){if(i(t),0===t.length)return".";for(var e=t.charCodeAt(0),a=47===e,n=-1,o=!0,l=t.length-1;l>=1;--l)if(47===(e=t.charCodeAt(l))){if(!o){n=l;break}}else o=!1;return-1===n?a?"/":".":a&&1===n?"//":t.slice(0,n)},basename:function(t,e){if(void 0!==e&&"string"!=typeof e)throw new TypeError('"ext" argument must be a string');i(t);var a,n=0,o=-1,l=!0;if(void 0!==e&&e.length>0&&e.length<=t.length){if(e.length===t.length&&e===t)return"";var r=e.length-1,p=-1;for(a=t.length-1;a>=0;--a){var s=t.charCodeAt(a);if(47===s){if(!l){n=a+1;break}}else-1===p&&(l=!1,p=a+1),r>=0&&(s===e.charCodeAt(r)?-1==--r&&(o=a):(r=-1,o=p))}return n===o?o=p:-1===o&&(o=t.length),t.slice(n,o)}for(a=t.length-1;a>=0;--a)if(47===t.charCodeAt(a)){if(!l){n=a+1;break}}else-1===o&&(l=!1,o=a+1);return-1===o?"":t.slice(n,o)},extname:function(t){i(t);for(var e=-1,a=0,n=-1,o=!0,l=0,r=t.length-1;r>=0;--r){var p=t.charCodeAt(r);if(47!==p)-1===n&&(o=!1,n=r+1),46===p?-1===e?e=r:1!==l&&(l=1):-1!==e&&(l=-1);else if(!o){a=r+1;break}}return-1===e||-1===n||0===l||1===l&&e===n-1&&e===a+1?"":t.slice(e,n)},format:function(t){if(null===t||"object"!=typeof t)throw new TypeError('The "pathObject" argument must be of type Object. Received type '+typeof t);return function(t,e){var i=e.dir||e.root,a=e.base||(e.name||"")+(e.ext||"");return i?i===e.root?i+a:i+"/"+a:a}(0,t)},parse:function(t){i(t);var e={root:"",dir:"",base:"",ext:"",name:""};if(0===t.length)return e;var a,n=t.charCodeAt(0),o=47===n;o?(e.root="/",a=1):a=0;for(var l=-1,r=0,p=-1,s=!0,c=t.length-1,d=0;c>=a;--c)if(47!==(n=t.charCodeAt(c)))-1===p&&(s=!1,p=c+1),46===n?-1===l?l=c:1!==d&&(d=1):-1!==l&&(d=-1);else if(!s){r=c+1;break}return-1===l||-1===p||0===d||1===d&&l===p-1&&l===r+1?-1!==p&&(e.base=e.name=0===r&&o?t.slice(1,p):t.slice(r,p)):(0===r&&o?(e.name=t.slice(1,l),e.base=t.slice(1,p)):(e.name=t.slice(r,l),e.base=t.slice(r,p)),e.ext=t.slice(l,p)),r>0?e.dir=t.slice(0,r-1):o&&(e.dir="/"),e},sep:"/",delimiter:":",win32:null,posix:null};n.posix=n,e.exports=n})),dt=F(((t,e)=>{e.exports=function(t,e){if(e=e.split(":")[0],!(t=+t))return!1;switch(e){case"http":case"ws":return 80!==t;case"https":case"wss":return 443!==t;case"ftp":return 21!==t;case"gopher":return 70!==t;case"file":return!1}return 0!==t}})),ut=F((t=>{var e=Object.prototype.hasOwnProperty;function i(t){try{return decodeURIComponent(t.replace(/\+/g," "))}catch{return null}}function a(t){try{return encodeURIComponent(t)}catch{return null}}t.stringify=function(t,i){i=i||"";var n,o,l=[];for(o in"string"!=typeof i&&(i="?"),t)if(e.call(t,o)){if(!(n=t[o])&&(null==n||isNaN(n))&&(n=""),o=a(o),n=a(n),null===o||null===n)continue;l.push(o+"="+n)}return l.length?i+l.join("&"):""},t.parse=function(t){for(var e,a=/([^=?#&]+)=?([^&]*)/g,n={};e=a.exec(t);){var o=i(e[1]),l=i(e[2]);null===o||null===l||o in n||(n[o]=l)}return n}})),_t=F(((t,e)=>{var i=dt(),a=ut(),n=/^[\x00-\x20\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/,o=/[\n\r\t]/g,l=/^[A-Za-z][A-Za-z0-9+-.]*:\/\//,r=/:\d+$/,p=/^([a-z][a-z0-9.+-]*:)?(\/\/)?([\\/]+)?([\S\s]*)/i,s=/^[a-zA-Z]:/;function c(t){return(t||"").toString().replace(n,"")}var d=[["#","hash"],["?","query"],function(t,e){return f(e.protocol)?t.replace(/\\/g,"/"):t},["/","pathname"],["@","auth",1],[NaN,"host",void 0,1,1],[/:(\d*)$/,"port",void 0,1],[NaN,"hostname",void 0,1,1]],m={hash:1,query:1};function u(t){var e,i=("undefined"!=typeof window?window:void 0!==__webpack_require__.g?__webpack_require__.g:"undefined"!=typeof self?self:{}).location||{},a={},n=typeof(t=t||i);if("blob:"===t.protocol)a=new v(unescape(t.pathname),{});else if("string"===n)for(e in a=new v(t,{}),m)delete a[e];else if("object"===n){for(e in t)e in m||(a[e]=t[e]);void 0===a.slashes&&(a.slashes=l.test(t.href))}return a}function f(t){return"file:"===t||"ftp:"===t||"http:"===t||"https:"===t||"ws:"===t||"wss:"===t}function h(t,e){t=(t=c(t)).replace(o,""),e=e||{};var i,a=p.exec(t),n=a[1]?a[1].toLowerCase():"",l=!!a[2],r=!!a[3],s=0;return l?r?(i=a[2]+a[3]+a[4],s=a[2].length+a[3].length):(i=a[2]+a[4],s=a[2].length):r?(i=a[3]+a[4],s=a[3].length):i=a[4],"file:"===n?s>=2&&(i=i.slice(2)):f(n)?i=a[4]:n?l&&(i=i.slice(2)):s>=2&&f(e.protocol)&&(i=a[4]),{protocol:n,slashes:l||f(n),slashesCount:s,rest:i}}function v(t,e,n){if(t=(t=c(t)).replace(o,""),!(this instanceof v))return new v(t,e,n);var l,r,p,m,x,g,b=d.slice(),w=typeof e,y=this,_=0;for("object"!==w&&"string"!==w&&(n=e,e=null),n&&"function"!=typeof n&&(n=a.parse),l=!(r=h(t||"",e=u(e))).protocol&&!r.slashes,y.slashes=r.slashes||l&&e.slashes,y.protocol=r.protocol||e.protocol||"",t=r.rest,("file:"===r.protocol&&(2!==r.slashesCount||s.test(t))||!r.slashes&&(r.protocol||r.slashesCount<2||!f(y.protocol)))&&(b[3]=[/(.*)/,"pathname"]);_{var e=t&&t.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(t,"__esModule",{value:!0}),t.URLExt=void 0;var i=ke(),a=e(_t());!function(t){function e(t){if("undefined"!=typeof document&&document){let e=document.createElement("a");return e.href=t,e}return(0,a.default)(t)}function n(...t){let e=(0,a.default)(t[0],{}),n=""===e.protocol&&e.slashes;n&&(e=(0,a.default)(t[0],"https:"+t[0]));let o=`${n?"":e.protocol}${e.slashes?"//":""}${e.auth}${e.auth?"@":""}${e.host}`,l=i.posix.join(`${o&&"/"!==e.pathname[0]?"/":""}${e.pathname}`,...t.slice(1));return`${o}${"."===l?"":l}`}t.parse=e,t.getHostName=function(t){return(0,a.default)(t).hostname},t.normalize=function(t){return t&&e(t).toString()},t.join=n,t.encodeParts=function(t){return n(...t.split("/").map(encodeURIComponent))},t.objectToQueryString=function(t){let e=Object.keys(t).filter((t=>t.length>0));return e.length?"?"+e.map((e=>{let i=encodeURIComponent(String(t[e]));return e+(i?"="+i:"")})).join("&"):""},t.queryStringToObject=function(t){return t.replace(/^\?/,"").split("&").reduce(((t,e)=>{let[i,a]=e.split("=");return i.length>0&&(t[i]=decodeURIComponent(a||"")),t}),{})},t.isLocal=function(t){let{protocol:i}=e(t);return(!i||0!==t.toLowerCase().indexOf(i))&&0!==t.indexOf("/")}}(t.URLExt||(t.URLExt={}))})),kt=F(((exports,module)=>{var __importDefault=exports&&exports.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.PageConfig=void 0;var coreutils_1=pe(),minimist_1=__importDefault(rt()),url_1=Ne(),PageConfig;(function(PageConfig){function getOption(name){if(configData)return configData[name]||getBodyData(name);configData=Object.create(null);let found=!1;if("undefined"!=typeof document&&document){let t=document.getElementById("jupyter-config-data");t&&(configData=JSON.parse(t.textContent||""),found=!0)}if(!found&&"undefined"!=typeof process&&process.argv)try{let cli=(0,minimist_1.default)(process.argv.slice(2)),path=ke(),fullPath="";"jupyter-config-data"in cli?fullPath=path.resolve(cli["jupyter-config-data"]):"JUPYTER_CONFIG_DATA"in{}&&(fullPath=path.resolve({}.JUPYTER_CONFIG_DATA)),fullPath&&(configData=eval("require")(fullPath))}catch(t){console.error(t)}if(coreutils_1.JSONExt.isObject(configData))for(let t in configData)"string"!=typeof configData[t]&&(configData[t]=JSON.stringify(configData[t]));else configData=Object.create(null);return configData[name]||getBodyData(name)}function setOption(t,e){let i=getOption(t);return configData[t]=e,i}function getBaseUrl(){return url_1.URLExt.normalize(getOption("baseUrl")||"/")}function getTreeUrl(){return url_1.URLExt.join(getBaseUrl(),getOption("treeUrl"))}function getShareUrl(){return url_1.URLExt.normalize(getOption("shareUrl")||getBaseUrl())}function getTreeShareUrl(){return url_1.URLExt.normalize(url_1.URLExt.join(getShareUrl(),getOption("treeUrl")))}function getUrl(t){var e,i,a,n;let o=t.toShare?getShareUrl():getBaseUrl(),l=null!==(e=t.mode)&&void 0!==e?e:getOption("mode"),r=null!==(i=t.workspace)&&void 0!==i?i:getOption("workspace"),p="single-document"===l?"doc":"lab";o=url_1.URLExt.join(o,p),r!==PageConfig.defaultWorkspace&&(o=url_1.URLExt.join(o,"workspaces",encodeURIComponent(null!==(a=getOption("workspace"))&&void 0!==a?a:PageConfig.defaultWorkspace)));let s=null!==(n=t.treePath)&&void 0!==n?n:getOption("treePath");return s&&(o=url_1.URLExt.join(o,"tree",url_1.URLExt.encodeParts(s))),o}function getWsUrl(t){let e=getOption("wsUrl");if(!e){if(0!==(t=t?url_1.URLExt.normalize(t):getBaseUrl()).indexOf("http"))return"";e="ws"+t.slice(4)}return url_1.URLExt.normalize(e)}function getNBConvertURL({path:t,format:e,download:i}){let a=url_1.URLExt.encodeParts(t),n=url_1.URLExt.join(getBaseUrl(),"nbconvert",e,a);return i?n+"?download=true":n}function getToken(){return getOption("token")||getBodyData("jupyterApiToken")}function getNotebookVersion(){let t=getOption("notebookVersion");return""===t?[0,0,0]:JSON.parse(t)}PageConfig.getOption=getOption,PageConfig.setOption=setOption,PageConfig.getBaseUrl=getBaseUrl,PageConfig.getTreeUrl=getTreeUrl,PageConfig.getShareUrl=getShareUrl,PageConfig.getTreeShareUrl=getTreeShareUrl,PageConfig.getUrl=getUrl,PageConfig.defaultWorkspace="default",PageConfig.getWsUrl=getWsUrl,PageConfig.getNBConvertURL=getNBConvertURL,PageConfig.getToken=getToken,PageConfig.getNotebookVersion=getNotebookVersion;let configData=null,Extension;function getBodyData(t){if("undefined"==typeof document||!document.body)return"";let e=document.body.dataset[t];return void 0===e?"":decodeURIComponent(e)}!function(t){function e(t){try{let e=getOption(t);if(e)return JSON.parse(e)}catch(e){console.warn(`Unable to parse ${t}.`,e)}return[]}t.deferred=e("deferredExtensions"),t.disabled=e("disabledExtensions"),t.isDeferred=function(e){let i=e.indexOf(":"),a="";return-1!==i&&(a=e.slice(0,i)),t.deferred.some((t=>t===e||a&&t===a))},t.isDisabled=function(e){let i=e.indexOf(":"),a="";return-1!==i&&(a=e.slice(0,i)),t.disabled.some((t=>t===e||a&&t===a))}}(Extension=PageConfig.Extension||(PageConfig.Extension={}))})(PageConfig=exports.PageConfig||(exports.PageConfig={}))})),jt=F((t=>{Object.defineProperty(t,"__esModule",{value:!0}),t.PathExt=void 0;var e=ke();!function(t){function i(t){return 0===t.indexOf("/")&&(t=t.slice(1)),t}t.join=function(...t){let a=e.posix.join(...t);return"."===a?"":i(a)},t.basename=function(t,i){return e.posix.basename(t,i)},t.dirname=function(t){let a=i(e.posix.dirname(t));return"."===a?"":a},t.extname=function(t){return e.posix.extname(t)},t.normalize=function(t){return""===t?"":i(e.posix.normalize(t))},t.resolve=function(...t){return i(e.posix.resolve(...t))},t.relative=function(t,a){return i(e.posix.relative(t,a))},t.normalizeExtension=function(t){return t.length>0&&0!==t.indexOf(".")&&(t=`.${t}`),t},t.removeSlash=i}(t.PathExt||(t.PathExt={}))})),Ct=F((t=>{Object.defineProperty(t,"__esModule",{value:!0}),t.signalToPromise=void 0;var e=pe();t.signalToPromise=function(t,i){let a=new e.PromiseDelegate;function n(){t.disconnect(o)}function o(t,e){n(),a.resolve([t,e])}return t.connect(o),(null!=i?i:0)>0&&setTimeout((()=>{n(),a.reject(`Signal not emitted within ${i} ms.`)}),i),a.promise}})),Ot=F((t=>{var e;Object.defineProperty(t,"__esModule",{value:!0}),t.Text=void 0,(e=t.Text||(t.Text={})).jsIndexToCharIndex=function(t,e){return t},e.charIndexToJsIndex=function(t,e){return t},e.camelCase=function(t,e=!1){return t.replace(/^(\w)|[\s-_:]+(\w)/g,(function(t,i,a){return a?a.toUpperCase():e?i.toUpperCase():i.toLowerCase()}))},e.titleCase=function(t){return(t||"").toLowerCase().split(" ").map((t=>t.charAt(0).toUpperCase()+t.slice(1))).join(" ")}})),Pt=F((t=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Time=void 0;var e,i=[{name:"years",milliseconds:31536e6},{name:"months",milliseconds:2592e6},{name:"days",milliseconds:864e5},{name:"hours",milliseconds:36e5},{name:"minutes",milliseconds:6e4},{name:"seconds",milliseconds:1e3}];(e=t.Time||(t.Time={})).formatHuman=function(t){let e=document.documentElement.lang||"en",a=new Intl.RelativeTimeFormat(e,{numeric:"auto"}),n=new Date(t).getTime()-Date.now();for(let t of i){let e=Math.ceil(n/t.milliseconds);if(0!==e)return a.format(e,t.name)}return a.format(0,"seconds")},e.format=function(t){let e=document.documentElement.lang||"en";return new Intl.DateTimeFormat(e,{dateStyle:"short",timeStyle:"short"}).format(new Date(t))}})),xe=F((t=>{var e=t&&t.__createBinding||(Object.create?function(t,e,i,a){void 0===a&&(a=i);var n=Object.getOwnPropertyDescriptor(e,i);(!n||("get"in n?!e.__esModule:n.writable||n.configurable))&&(n={enumerable:!0,get:function(){return e[i]}}),Object.defineProperty(t,a,n)}:function(t,e,i,a){void 0===a&&(a=i),t[a]=e[i]}),i=t&&t.__exportStar||function(t,i){for(var a in t)"default"!==a&&!Object.prototype.hasOwnProperty.call(i,a)&&e(i,t,a)};Object.defineProperty(t,"__esModule",{value:!0}),i(et(),t),i(it(),t),i(nt(),t),i(kt(),t),i(jt(),t),i(Ct(),t),i(Ot(),t),i(Pt(),t),i(Ne(),t)})),zt=F(((t,e)=>{function i(){this._types=Object.create(null),this._extensions=Object.create(null);for(let t=0;t{e.exports={"application/andrew-inset":["ez"],"application/applixware":["aw"],"application/atom+xml":["atom"],"application/atomcat+xml":["atomcat"],"application/atomdeleted+xml":["atomdeleted"],"application/atomsvc+xml":["atomsvc"],"application/atsc-dwd+xml":["dwd"],"application/atsc-held+xml":["held"],"application/atsc-rsat+xml":["rsat"],"application/bdoc":["bdoc"],"application/calendar+xml":["xcs"],"application/ccxml+xml":["ccxml"],"application/cdfx+xml":["cdfx"],"application/cdmi-capability":["cdmia"],"application/cdmi-container":["cdmic"],"application/cdmi-domain":["cdmid"],"application/cdmi-object":["cdmio"],"application/cdmi-queue":["cdmiq"],"application/cu-seeme":["cu"],"application/dash+xml":["mpd"],"application/davmount+xml":["davmount"],"application/docbook+xml":["dbk"],"application/dssc+der":["dssc"],"application/dssc+xml":["xdssc"],"application/ecmascript":["es","ecma"],"application/emma+xml":["emma"],"application/emotionml+xml":["emotionml"],"application/epub+zip":["epub"],"application/exi":["exi"],"application/express":["exp"],"application/fdt+xml":["fdt"],"application/font-tdpfr":["pfr"],"application/geo+json":["geojson"],"application/gml+xml":["gml"],"application/gpx+xml":["gpx"],"application/gxf":["gxf"],"application/gzip":["gz"],"application/hjson":["hjson"],"application/hyperstudio":["stk"],"application/inkml+xml":["ink","inkml"],"application/ipfix":["ipfix"],"application/its+xml":["its"],"application/java-archive":["jar","war","ear"],"application/java-serialized-object":["ser"],"application/java-vm":["class"],"application/javascript":["js","mjs"],"application/json":["json","map"],"application/json5":["json5"],"application/jsonml+json":["jsonml"],"application/ld+json":["jsonld"],"application/lgr+xml":["lgr"],"application/lost+xml":["lostxml"],"application/mac-binhex40":["hqx"],"application/mac-compactpro":["cpt"],"application/mads+xml":["mads"],"application/manifest+json":["webmanifest"],"application/marc":["mrc"],"application/marcxml+xml":["mrcx"],"application/mathematica":["ma","nb","mb"],"application/mathml+xml":["mathml"],"application/mbox":["mbox"],"application/mediaservercontrol+xml":["mscml"],"application/metalink+xml":["metalink"],"application/metalink4+xml":["meta4"],"application/mets+xml":["mets"],"application/mmt-aei+xml":["maei"],"application/mmt-usd+xml":["musd"],"application/mods+xml":["mods"],"application/mp21":["m21","mp21"],"application/mp4":["mp4s","m4p"],"application/msword":["doc","dot"],"application/mxf":["mxf"],"application/n-quads":["nq"],"application/n-triples":["nt"],"application/node":["cjs"],"application/octet-stream":["bin","dms","lrf","mar","so","dist","distz","pkg","bpk","dump","elc","deploy","exe","dll","deb","dmg","iso","img","msi","msp","msm","buffer"],"application/oda":["oda"],"application/oebps-package+xml":["opf"],"application/ogg":["ogx"],"application/omdoc+xml":["omdoc"],"application/onenote":["onetoc","onetoc2","onetmp","onepkg"],"application/oxps":["oxps"],"application/p2p-overlay+xml":["relo"],"application/patch-ops-error+xml":["xer"],"application/pdf":["pdf"],"application/pgp-encrypted":["pgp"],"application/pgp-signature":["asc","sig"],"application/pics-rules":["prf"],"application/pkcs10":["p10"],"application/pkcs7-mime":["p7m","p7c"],"application/pkcs7-signature":["p7s"],"application/pkcs8":["p8"],"application/pkix-attr-cert":["ac"],"application/pkix-cert":["cer"],"application/pkix-crl":["crl"],"application/pkix-pkipath":["pkipath"],"application/pkixcmp":["pki"],"application/pls+xml":["pls"],"application/postscript":["ai","eps","ps"],"application/provenance+xml":["provx"],"application/pskc+xml":["pskcxml"],"application/raml+yaml":["raml"],"application/rdf+xml":["rdf","owl"],"application/reginfo+xml":["rif"],"application/relax-ng-compact-syntax":["rnc"],"application/resource-lists+xml":["rl"],"application/resource-lists-diff+xml":["rld"],"application/rls-services+xml":["rs"],"application/route-apd+xml":["rapd"],"application/route-s-tsid+xml":["sls"],"application/route-usd+xml":["rusd"],"application/rpki-ghostbusters":["gbr"],"application/rpki-manifest":["mft"],"application/rpki-roa":["roa"],"application/rsd+xml":["rsd"],"application/rss+xml":["rss"],"application/rtf":["rtf"],"application/sbml+xml":["sbml"],"application/scvp-cv-request":["scq"],"application/scvp-cv-response":["scs"],"application/scvp-vp-request":["spq"],"application/scvp-vp-response":["spp"],"application/sdp":["sdp"],"application/senml+xml":["senmlx"],"application/sensml+xml":["sensmlx"],"application/set-payment-initiation":["setpay"],"application/set-registration-initiation":["setreg"],"application/shf+xml":["shf"],"application/sieve":["siv","sieve"],"application/smil+xml":["smi","smil"],"application/sparql-query":["rq"],"application/sparql-results+xml":["srx"],"application/srgs":["gram"],"application/srgs+xml":["grxml"],"application/sru+xml":["sru"],"application/ssdl+xml":["ssdl"],"application/ssml+xml":["ssml"],"application/swid+xml":["swidtag"],"application/tei+xml":["tei","teicorpus"],"application/thraud+xml":["tfi"],"application/timestamped-data":["tsd"],"application/toml":["toml"],"application/trig":["trig"],"application/ttml+xml":["ttml"],"application/ubjson":["ubj"],"application/urc-ressheet+xml":["rsheet"],"application/urc-targetdesc+xml":["td"],"application/voicexml+xml":["vxml"],"application/wasm":["wasm"],"application/widget":["wgt"],"application/winhlp":["hlp"],"application/wsdl+xml":["wsdl"],"application/wspolicy+xml":["wspolicy"],"application/xaml+xml":["xaml"],"application/xcap-att+xml":["xav"],"application/xcap-caps+xml":["xca"],"application/xcap-diff+xml":["xdf"],"application/xcap-el+xml":["xel"],"application/xcap-ns+xml":["xns"],"application/xenc+xml":["xenc"],"application/xhtml+xml":["xhtml","xht"],"application/xliff+xml":["xlf"],"application/xml":["xml","xsl","xsd","rng"],"application/xml-dtd":["dtd"],"application/xop+xml":["xop"],"application/xproc+xml":["xpl"],"application/xslt+xml":["*xsl","xslt"],"application/xspf+xml":["xspf"],"application/xv+xml":["mxml","xhvml","xvml","xvm"],"application/yang":["yang"],"application/yin+xml":["yin"],"application/zip":["zip"],"audio/3gpp":["*3gpp"],"audio/adpcm":["adp"],"audio/amr":["amr"],"audio/basic":["au","snd"],"audio/midi":["mid","midi","kar","rmi"],"audio/mobile-xmf":["mxmf"],"audio/mp3":["*mp3"],"audio/mp4":["m4a","mp4a"],"audio/mpeg":["mpga","mp2","mp2a","mp3","m2a","m3a"],"audio/ogg":["oga","ogg","spx","opus"],"audio/s3m":["s3m"],"audio/silk":["sil"],"audio/wav":["wav"],"audio/wave":["*wav"],"audio/webm":["weba"],"audio/xm":["xm"],"font/collection":["ttc"],"font/otf":["otf"],"font/ttf":["ttf"],"font/woff":["woff"],"font/woff2":["woff2"],"image/aces":["exr"],"image/apng":["apng"],"image/avif":["avif"],"image/bmp":["bmp"],"image/cgm":["cgm"],"image/dicom-rle":["drle"],"image/emf":["emf"],"image/fits":["fits"],"image/g3fax":["g3"],"image/gif":["gif"],"image/heic":["heic"],"image/heic-sequence":["heics"],"image/heif":["heif"],"image/heif-sequence":["heifs"],"image/hej2k":["hej2"],"image/hsj2":["hsj2"],"image/ief":["ief"],"image/jls":["jls"],"image/jp2":["jp2","jpg2"],"image/jpeg":["jpeg","jpg","jpe"],"image/jph":["jph"],"image/jphc":["jhc"],"image/jpm":["jpm"],"image/jpx":["jpx","jpf"],"image/jxr":["jxr"],"image/jxra":["jxra"],"image/jxrs":["jxrs"],"image/jxs":["jxs"],"image/jxsc":["jxsc"],"image/jxsi":["jxsi"],"image/jxss":["jxss"],"image/ktx":["ktx"],"image/ktx2":["ktx2"],"image/png":["png"],"image/sgi":["sgi"],"image/svg+xml":["svg","svgz"],"image/t38":["t38"],"image/tiff":["tif","tiff"],"image/tiff-fx":["tfx"],"image/webp":["webp"],"image/wmf":["wmf"],"message/disposition-notification":["disposition-notification"],"message/global":["u8msg"],"message/global-delivery-status":["u8dsn"],"message/global-disposition-notification":["u8mdn"],"message/global-headers":["u8hdr"],"message/rfc822":["eml","mime"],"model/3mf":["3mf"],"model/gltf+json":["gltf"],"model/gltf-binary":["glb"],"model/iges":["igs","iges"],"model/mesh":["msh","mesh","silo"],"model/mtl":["mtl"],"model/obj":["obj"],"model/step+xml":["stpx"],"model/step+zip":["stpz"],"model/step-xml+zip":["stpxz"],"model/stl":["stl"],"model/vrml":["wrl","vrml"],"model/x3d+binary":["*x3db","x3dbz"],"model/x3d+fastinfoset":["x3db"],"model/x3d+vrml":["*x3dv","x3dvz"],"model/x3d+xml":["x3d","x3dz"],"model/x3d-vrml":["x3dv"],"text/cache-manifest":["appcache","manifest"],"text/calendar":["ics","ifb"],"text/coffeescript":["coffee","litcoffee"],"text/css":["css"],"text/csv":["csv"],"text/html":["html","htm","shtml"],"text/jade":["jade"],"text/jsx":["jsx"],"text/less":["less"],"text/markdown":["markdown","md"],"text/mathml":["mml"],"text/mdx":["mdx"],"text/n3":["n3"],"text/plain":["txt","text","conf","def","list","log","in","ini"],"text/richtext":["rtx"],"text/rtf":["*rtf"],"text/sgml":["sgml","sgm"],"text/shex":["shex"],"text/slim":["slim","slm"],"text/spdx":["spdx"],"text/stylus":["stylus","styl"],"text/tab-separated-values":["tsv"],"text/troff":["t","tr","roff","man","me","ms"],"text/turtle":["ttl"],"text/uri-list":["uri","uris","urls"],"text/vcard":["vcard"],"text/vtt":["vtt"],"text/xml":["*xml"],"text/yaml":["yaml","yml"],"video/3gpp":["3gp","3gpp"],"video/3gpp2":["3g2"],"video/h261":["h261"],"video/h263":["h263"],"video/h264":["h264"],"video/iso.segment":["m4s"],"video/jpeg":["jpgv"],"video/jpm":["*jpm","jpgm"],"video/mj2":["mj2","mjp2"],"video/mp2t":["ts"],"video/mp4":["mp4","mp4v","mpg4"],"video/mpeg":["mpeg","mpg","mpe","m1v","m2v"],"video/ogg":["ogv"],"video/quicktime":["qt","mov"],"video/webm":["webm"]}})),Dt=F(((t,e)=>{e.exports={"application/prs.cww":["cww"],"application/vnd.1000minds.decision-model+xml":["1km"],"application/vnd.3gpp.pic-bw-large":["plb"],"application/vnd.3gpp.pic-bw-small":["psb"],"application/vnd.3gpp.pic-bw-var":["pvb"],"application/vnd.3gpp2.tcap":["tcap"],"application/vnd.3m.post-it-notes":["pwn"],"application/vnd.accpac.simply.aso":["aso"],"application/vnd.accpac.simply.imp":["imp"],"application/vnd.acucobol":["acu"],"application/vnd.acucorp":["atc","acutc"],"application/vnd.adobe.air-application-installer-package+zip":["air"],"application/vnd.adobe.formscentral.fcdt":["fcdt"],"application/vnd.adobe.fxp":["fxp","fxpl"],"application/vnd.adobe.xdp+xml":["xdp"],"application/vnd.adobe.xfdf":["xfdf"],"application/vnd.ahead.space":["ahead"],"application/vnd.airzip.filesecure.azf":["azf"],"application/vnd.airzip.filesecure.azs":["azs"],"application/vnd.amazon.ebook":["azw"],"application/vnd.americandynamics.acc":["acc"],"application/vnd.amiga.ami":["ami"],"application/vnd.android.package-archive":["apk"],"application/vnd.anser-web-certificate-issue-initiation":["cii"],"application/vnd.anser-web-funds-transfer-initiation":["fti"],"application/vnd.antix.game-component":["atx"],"application/vnd.apple.installer+xml":["mpkg"],"application/vnd.apple.keynote":["key"],"application/vnd.apple.mpegurl":["m3u8"],"application/vnd.apple.numbers":["numbers"],"application/vnd.apple.pages":["pages"],"application/vnd.apple.pkpass":["pkpass"],"application/vnd.aristanetworks.swi":["swi"],"application/vnd.astraea-software.iota":["iota"],"application/vnd.audiograph":["aep"],"application/vnd.balsamiq.bmml+xml":["bmml"],"application/vnd.blueice.multipass":["mpm"],"application/vnd.bmi":["bmi"],"application/vnd.businessobjects":["rep"],"application/vnd.chemdraw+xml":["cdxml"],"application/vnd.chipnuts.karaoke-mmd":["mmd"],"application/vnd.cinderella":["cdy"],"application/vnd.citationstyles.style+xml":["csl"],"application/vnd.claymore":["cla"],"application/vnd.cloanto.rp9":["rp9"],"application/vnd.clonk.c4group":["c4g","c4d","c4f","c4p","c4u"],"application/vnd.cluetrust.cartomobile-config":["c11amc"],"application/vnd.cluetrust.cartomobile-config-pkg":["c11amz"],"application/vnd.commonspace":["csp"],"application/vnd.contact.cmsg":["cdbcmsg"],"application/vnd.cosmocaller":["cmc"],"application/vnd.crick.clicker":["clkx"],"application/vnd.crick.clicker.keyboard":["clkk"],"application/vnd.crick.clicker.palette":["clkp"],"application/vnd.crick.clicker.template":["clkt"],"application/vnd.crick.clicker.wordbank":["clkw"],"application/vnd.criticaltools.wbs+xml":["wbs"],"application/vnd.ctc-posml":["pml"],"application/vnd.cups-ppd":["ppd"],"application/vnd.curl.car":["car"],"application/vnd.curl.pcurl":["pcurl"],"application/vnd.dart":["dart"],"application/vnd.data-vision.rdz":["rdz"],"application/vnd.dbf":["dbf"],"application/vnd.dece.data":["uvf","uvvf","uvd","uvvd"],"application/vnd.dece.ttml+xml":["uvt","uvvt"],"application/vnd.dece.unspecified":["uvx","uvvx"],"application/vnd.dece.zip":["uvz","uvvz"],"application/vnd.denovo.fcselayout-link":["fe_launch"],"application/vnd.dna":["dna"],"application/vnd.dolby.mlp":["mlp"],"application/vnd.dpgraph":["dpg"],"application/vnd.dreamfactory":["dfac"],"application/vnd.ds-keypoint":["kpxx"],"application/vnd.dvb.ait":["ait"],"application/vnd.dvb.service":["svc"],"application/vnd.dynageo":["geo"],"application/vnd.ecowin.chart":["mag"],"application/vnd.enliven":["nml"],"application/vnd.epson.esf":["esf"],"application/vnd.epson.msf":["msf"],"application/vnd.epson.quickanime":["qam"],"application/vnd.epson.salt":["slt"],"application/vnd.epson.ssf":["ssf"],"application/vnd.eszigno3+xml":["es3","et3"],"application/vnd.ezpix-album":["ez2"],"application/vnd.ezpix-package":["ez3"],"application/vnd.fdf":["fdf"],"application/vnd.fdsn.mseed":["mseed"],"application/vnd.fdsn.seed":["seed","dataless"],"application/vnd.flographit":["gph"],"application/vnd.fluxtime.clip":["ftc"],"application/vnd.framemaker":["fm","frame","maker","book"],"application/vnd.frogans.fnc":["fnc"],"application/vnd.frogans.ltf":["ltf"],"application/vnd.fsc.weblaunch":["fsc"],"application/vnd.fujitsu.oasys":["oas"],"application/vnd.fujitsu.oasys2":["oa2"],"application/vnd.fujitsu.oasys3":["oa3"],"application/vnd.fujitsu.oasysgp":["fg5"],"application/vnd.fujitsu.oasysprs":["bh2"],"application/vnd.fujixerox.ddd":["ddd"],"application/vnd.fujixerox.docuworks":["xdw"],"application/vnd.fujixerox.docuworks.binder":["xbd"],"application/vnd.fuzzysheet":["fzs"],"application/vnd.genomatix.tuxedo":["txd"],"application/vnd.geogebra.file":["ggb"],"application/vnd.geogebra.tool":["ggt"],"application/vnd.geometry-explorer":["gex","gre"],"application/vnd.geonext":["gxt"],"application/vnd.geoplan":["g2w"],"application/vnd.geospace":["g3w"],"application/vnd.gmx":["gmx"],"application/vnd.google-apps.document":["gdoc"],"application/vnd.google-apps.presentation":["gslides"],"application/vnd.google-apps.spreadsheet":["gsheet"],"application/vnd.google-earth.kml+xml":["kml"],"application/vnd.google-earth.kmz":["kmz"],"application/vnd.grafeq":["gqf","gqs"],"application/vnd.groove-account":["gac"],"application/vnd.groove-help":["ghf"],"application/vnd.groove-identity-message":["gim"],"application/vnd.groove-injector":["grv"],"application/vnd.groove-tool-message":["gtm"],"application/vnd.groove-tool-template":["tpl"],"application/vnd.groove-vcard":["vcg"],"application/vnd.hal+xml":["hal"],"application/vnd.handheld-entertainment+xml":["zmm"],"application/vnd.hbci":["hbci"],"application/vnd.hhe.lesson-player":["les"],"application/vnd.hp-hpgl":["hpgl"],"application/vnd.hp-hpid":["hpid"],"application/vnd.hp-hps":["hps"],"application/vnd.hp-jlyt":["jlt"],"application/vnd.hp-pcl":["pcl"],"application/vnd.hp-pclxl":["pclxl"],"application/vnd.hydrostatix.sof-data":["sfd-hdstx"],"application/vnd.ibm.minipay":["mpy"],"application/vnd.ibm.modcap":["afp","listafp","list3820"],"application/vnd.ibm.rights-management":["irm"],"application/vnd.ibm.secure-container":["sc"],"application/vnd.iccprofile":["icc","icm"],"application/vnd.igloader":["igl"],"application/vnd.immervision-ivp":["ivp"],"application/vnd.immervision-ivu":["ivu"],"application/vnd.insors.igm":["igm"],"application/vnd.intercon.formnet":["xpw","xpx"],"application/vnd.intergeo":["i2g"],"application/vnd.intu.qbo":["qbo"],"application/vnd.intu.qfx":["qfx"],"application/vnd.ipunplugged.rcprofile":["rcprofile"],"application/vnd.irepository.package+xml":["irp"],"application/vnd.is-xpr":["xpr"],"application/vnd.isac.fcs":["fcs"],"application/vnd.jam":["jam"],"application/vnd.jcp.javame.midlet-rms":["rms"],"application/vnd.jisp":["jisp"],"application/vnd.joost.joda-archive":["joda"],"application/vnd.kahootz":["ktz","ktr"],"application/vnd.kde.karbon":["karbon"],"application/vnd.kde.kchart":["chrt"],"application/vnd.kde.kformula":["kfo"],"application/vnd.kde.kivio":["flw"],"application/vnd.kde.kontour":["kon"],"application/vnd.kde.kpresenter":["kpr","kpt"],"application/vnd.kde.kspread":["ksp"],"application/vnd.kde.kword":["kwd","kwt"],"application/vnd.kenameaapp":["htke"],"application/vnd.kidspiration":["kia"],"application/vnd.kinar":["kne","knp"],"application/vnd.koan":["skp","skd","skt","skm"],"application/vnd.kodak-descriptor":["sse"],"application/vnd.las.las+xml":["lasxml"],"application/vnd.llamagraphics.life-balance.desktop":["lbd"],"application/vnd.llamagraphics.life-balance.exchange+xml":["lbe"],"application/vnd.lotus-1-2-3":["123"],"application/vnd.lotus-approach":["apr"],"application/vnd.lotus-freelance":["pre"],"application/vnd.lotus-notes":["nsf"],"application/vnd.lotus-organizer":["org"],"application/vnd.lotus-screencam":["scm"],"application/vnd.lotus-wordpro":["lwp"],"application/vnd.macports.portpkg":["portpkg"],"application/vnd.mapbox-vector-tile":["mvt"],"application/vnd.mcd":["mcd"],"application/vnd.medcalcdata":["mc1"],"application/vnd.mediastation.cdkey":["cdkey"],"application/vnd.mfer":["mwf"],"application/vnd.mfmp":["mfm"],"application/vnd.micrografx.flo":["flo"],"application/vnd.micrografx.igx":["igx"],"application/vnd.mif":["mif"],"application/vnd.mobius.daf":["daf"],"application/vnd.mobius.dis":["dis"],"application/vnd.mobius.mbk":["mbk"],"application/vnd.mobius.mqy":["mqy"],"application/vnd.mobius.msl":["msl"],"application/vnd.mobius.plc":["plc"],"application/vnd.mobius.txf":["txf"],"application/vnd.mophun.application":["mpn"],"application/vnd.mophun.certificate":["mpc"],"application/vnd.mozilla.xul+xml":["xul"],"application/vnd.ms-artgalry":["cil"],"application/vnd.ms-cab-compressed":["cab"],"application/vnd.ms-excel":["xls","xlm","xla","xlc","xlt","xlw"],"application/vnd.ms-excel.addin.macroenabled.12":["xlam"],"application/vnd.ms-excel.sheet.binary.macroenabled.12":["xlsb"],"application/vnd.ms-excel.sheet.macroenabled.12":["xlsm"],"application/vnd.ms-excel.template.macroenabled.12":["xltm"],"application/vnd.ms-fontobject":["eot"],"application/vnd.ms-htmlhelp":["chm"],"application/vnd.ms-ims":["ims"],"application/vnd.ms-lrm":["lrm"],"application/vnd.ms-officetheme":["thmx"],"application/vnd.ms-outlook":["msg"],"application/vnd.ms-pki.seccat":["cat"],"application/vnd.ms-pki.stl":["*stl"],"application/vnd.ms-powerpoint":["ppt","pps","pot"],"application/vnd.ms-powerpoint.addin.macroenabled.12":["ppam"],"application/vnd.ms-powerpoint.presentation.macroenabled.12":["pptm"],"application/vnd.ms-powerpoint.slide.macroenabled.12":["sldm"],"application/vnd.ms-powerpoint.slideshow.macroenabled.12":["ppsm"],"application/vnd.ms-powerpoint.template.macroenabled.12":["potm"],"application/vnd.ms-project":["mpp","mpt"],"application/vnd.ms-word.document.macroenabled.12":["docm"],"application/vnd.ms-word.template.macroenabled.12":["dotm"],"application/vnd.ms-works":["wps","wks","wcm","wdb"],"application/vnd.ms-wpl":["wpl"],"application/vnd.ms-xpsdocument":["xps"],"application/vnd.mseq":["mseq"],"application/vnd.musician":["mus"],"application/vnd.muvee.style":["msty"],"application/vnd.mynfc":["taglet"],"application/vnd.neurolanguage.nlu":["nlu"],"application/vnd.nitf":["ntf","nitf"],"application/vnd.noblenet-directory":["nnd"],"application/vnd.noblenet-sealer":["nns"],"application/vnd.noblenet-web":["nnw"],"application/vnd.nokia.n-gage.ac+xml":["*ac"],"application/vnd.nokia.n-gage.data":["ngdat"],"application/vnd.nokia.n-gage.symbian.install":["n-gage"],"application/vnd.nokia.radio-preset":["rpst"],"application/vnd.nokia.radio-presets":["rpss"],"application/vnd.novadigm.edm":["edm"],"application/vnd.novadigm.edx":["edx"],"application/vnd.novadigm.ext":["ext"],"application/vnd.oasis.opendocument.chart":["odc"],"application/vnd.oasis.opendocument.chart-template":["otc"],"application/vnd.oasis.opendocument.database":["odb"],"application/vnd.oasis.opendocument.formula":["odf"],"application/vnd.oasis.opendocument.formula-template":["odft"],"application/vnd.oasis.opendocument.graphics":["odg"],"application/vnd.oasis.opendocument.graphics-template":["otg"],"application/vnd.oasis.opendocument.image":["odi"],"application/vnd.oasis.opendocument.image-template":["oti"],"application/vnd.oasis.opendocument.presentation":["odp"],"application/vnd.oasis.opendocument.presentation-template":["otp"],"application/vnd.oasis.opendocument.spreadsheet":["ods"],"application/vnd.oasis.opendocument.spreadsheet-template":["ots"],"application/vnd.oasis.opendocument.text":["odt"],"application/vnd.oasis.opendocument.text-master":["odm"],"application/vnd.oasis.opendocument.text-template":["ott"],"application/vnd.oasis.opendocument.text-web":["oth"],"application/vnd.olpc-sugar":["xo"],"application/vnd.oma.dd2+xml":["dd2"],"application/vnd.openblox.game+xml":["obgx"],"application/vnd.openofficeorg.extension":["oxt"],"application/vnd.openstreetmap.data+xml":["osm"],"application/vnd.openxmlformats-officedocument.presentationml.presentation":["pptx"],"application/vnd.openxmlformats-officedocument.presentationml.slide":["sldx"],"application/vnd.openxmlformats-officedocument.presentationml.slideshow":["ppsx"],"application/vnd.openxmlformats-officedocument.presentationml.template":["potx"],"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":["xlsx"],"application/vnd.openxmlformats-officedocument.spreadsheetml.template":["xltx"],"application/vnd.openxmlformats-officedocument.wordprocessingml.document":["docx"],"application/vnd.openxmlformats-officedocument.wordprocessingml.template":["dotx"],"application/vnd.osgeo.mapguide.package":["mgp"],"application/vnd.osgi.dp":["dp"],"application/vnd.osgi.subsystem":["esa"],"application/vnd.palm":["pdb","pqa","oprc"],"application/vnd.pawaafile":["paw"],"application/vnd.pg.format":["str"],"application/vnd.pg.osasli":["ei6"],"application/vnd.picsel":["efif"],"application/vnd.pmi.widget":["wg"],"application/vnd.pocketlearn":["plf"],"application/vnd.powerbuilder6":["pbd"],"application/vnd.previewsystems.box":["box"],"application/vnd.proteus.magazine":["mgz"],"application/vnd.publishare-delta-tree":["qps"],"application/vnd.pvi.ptid1":["ptid"],"application/vnd.quark.quarkxpress":["qxd","qxt","qwd","qwt","qxl","qxb"],"application/vnd.rar":["rar"],"application/vnd.realvnc.bed":["bed"],"application/vnd.recordare.musicxml":["mxl"],"application/vnd.recordare.musicxml+xml":["musicxml"],"application/vnd.rig.cryptonote":["cryptonote"],"application/vnd.rim.cod":["cod"],"application/vnd.rn-realmedia":["rm"],"application/vnd.rn-realmedia-vbr":["rmvb"],"application/vnd.route66.link66+xml":["link66"],"application/vnd.sailingtracker.track":["st"],"application/vnd.seemail":["see"],"application/vnd.sema":["sema"],"application/vnd.semd":["semd"],"application/vnd.semf":["semf"],"application/vnd.shana.informed.formdata":["ifm"],"application/vnd.shana.informed.formtemplate":["itp"],"application/vnd.shana.informed.interchange":["iif"],"application/vnd.shana.informed.package":["ipk"],"application/vnd.simtech-mindmapper":["twd","twds"],"application/vnd.smaf":["mmf"],"application/vnd.smart.teacher":["teacher"],"application/vnd.software602.filler.form+xml":["fo"],"application/vnd.solent.sdkm+xml":["sdkm","sdkd"],"application/vnd.spotfire.dxp":["dxp"],"application/vnd.spotfire.sfs":["sfs"],"application/vnd.stardivision.calc":["sdc"],"application/vnd.stardivision.draw":["sda"],"application/vnd.stardivision.impress":["sdd"],"application/vnd.stardivision.math":["smf"],"application/vnd.stardivision.writer":["sdw","vor"],"application/vnd.stardivision.writer-global":["sgl"],"application/vnd.stepmania.package":["smzip"],"application/vnd.stepmania.stepchart":["sm"],"application/vnd.sun.wadl+xml":["wadl"],"application/vnd.sun.xml.calc":["sxc"],"application/vnd.sun.xml.calc.template":["stc"],"application/vnd.sun.xml.draw":["sxd"],"application/vnd.sun.xml.draw.template":["std"],"application/vnd.sun.xml.impress":["sxi"],"application/vnd.sun.xml.impress.template":["sti"],"application/vnd.sun.xml.math":["sxm"],"application/vnd.sun.xml.writer":["sxw"],"application/vnd.sun.xml.writer.global":["sxg"],"application/vnd.sun.xml.writer.template":["stw"],"application/vnd.sus-calendar":["sus","susp"],"application/vnd.svd":["svd"],"application/vnd.symbian.install":["sis","sisx"],"application/vnd.syncml+xml":["xsm"],"application/vnd.syncml.dm+wbxml":["bdm"],"application/vnd.syncml.dm+xml":["xdm"],"application/vnd.syncml.dmddf+xml":["ddf"],"application/vnd.tao.intent-module-archive":["tao"],"application/vnd.tcpdump.pcap":["pcap","cap","dmp"],"application/vnd.tmobile-livetv":["tmo"],"application/vnd.trid.tpt":["tpt"],"application/vnd.triscape.mxs":["mxs"],"application/vnd.trueapp":["tra"],"application/vnd.ufdl":["ufd","ufdl"],"application/vnd.uiq.theme":["utz"],"application/vnd.umajin":["umj"],"application/vnd.unity":["unityweb"],"application/vnd.uoml+xml":["uoml"],"application/vnd.vcx":["vcx"],"application/vnd.visio":["vsd","vst","vss","vsw"],"application/vnd.visionary":["vis"],"application/vnd.vsf":["vsf"],"application/vnd.wap.wbxml":["wbxml"],"application/vnd.wap.wmlc":["wmlc"],"application/vnd.wap.wmlscriptc":["wmlsc"],"application/vnd.webturbo":["wtb"],"application/vnd.wolfram.player":["nbp"],"application/vnd.wordperfect":["wpd"],"application/vnd.wqd":["wqd"],"application/vnd.wt.stf":["stf"],"application/vnd.xara":["xar"],"application/vnd.xfdl":["xfdl"],"application/vnd.yamaha.hv-dic":["hvd"],"application/vnd.yamaha.hv-script":["hvs"],"application/vnd.yamaha.hv-voice":["hvp"],"application/vnd.yamaha.openscoreformat":["osf"],"application/vnd.yamaha.openscoreformat.osfpvg+xml":["osfpvg"],"application/vnd.yamaha.smaf-audio":["saf"],"application/vnd.yamaha.smaf-phrase":["spf"],"application/vnd.yellowriver-custom-menu":["cmp"],"application/vnd.zul":["zir","zirz"],"application/vnd.zzazz.deck+xml":["zaz"],"application/x-7z-compressed":["7z"],"application/x-abiword":["abw"],"application/x-ace-compressed":["ace"],"application/x-apple-diskimage":["*dmg"],"application/x-arj":["arj"],"application/x-authorware-bin":["aab","x32","u32","vox"],"application/x-authorware-map":["aam"],"application/x-authorware-seg":["aas"],"application/x-bcpio":["bcpio"],"application/x-bdoc":["*bdoc"],"application/x-bittorrent":["torrent"],"application/x-blorb":["blb","blorb"],"application/x-bzip":["bz"],"application/x-bzip2":["bz2","boz"],"application/x-cbr":["cbr","cba","cbt","cbz","cb7"],"application/x-cdlink":["vcd"],"application/x-cfs-compressed":["cfs"],"application/x-chat":["chat"],"application/x-chess-pgn":["pgn"],"application/x-chrome-extension":["crx"],"application/x-cocoa":["cco"],"application/x-conference":["nsc"],"application/x-cpio":["cpio"],"application/x-csh":["csh"],"application/x-debian-package":["*deb","udeb"],"application/x-dgc-compressed":["dgc"],"application/x-director":["dir","dcr","dxr","cst","cct","cxt","w3d","fgd","swa"],"application/x-doom":["wad"],"application/x-dtbncx+xml":["ncx"],"application/x-dtbook+xml":["dtb"],"application/x-dtbresource+xml":["res"],"application/x-dvi":["dvi"],"application/x-envoy":["evy"],"application/x-eva":["eva"],"application/x-font-bdf":["bdf"],"application/x-font-ghostscript":["gsf"],"application/x-font-linux-psf":["psf"],"application/x-font-pcf":["pcf"],"application/x-font-snf":["snf"],"application/x-font-type1":["pfa","pfb","pfm","afm"],"application/x-freearc":["arc"],"application/x-futuresplash":["spl"],"application/x-gca-compressed":["gca"],"application/x-glulx":["ulx"],"application/x-gnumeric":["gnumeric"],"application/x-gramps-xml":["gramps"],"application/x-gtar":["gtar"],"application/x-hdf":["hdf"],"application/x-httpd-php":["php"],"application/x-install-instructions":["install"],"application/x-iso9660-image":["*iso"],"application/x-iwork-keynote-sffkey":["*key"],"application/x-iwork-numbers-sffnumbers":["*numbers"],"application/x-iwork-pages-sffpages":["*pages"],"application/x-java-archive-diff":["jardiff"],"application/x-java-jnlp-file":["jnlp"],"application/x-keepass2":["kdbx"],"application/x-latex":["latex"],"application/x-lua-bytecode":["luac"],"application/x-lzh-compressed":["lzh","lha"],"application/x-makeself":["run"],"application/x-mie":["mie"],"application/x-mobipocket-ebook":["prc","mobi"],"application/x-ms-application":["application"],"application/x-ms-shortcut":["lnk"],"application/x-ms-wmd":["wmd"],"application/x-ms-wmz":["wmz"],"application/x-ms-xbap":["xbap"],"application/x-msaccess":["mdb"],"application/x-msbinder":["obd"],"application/x-mscardfile":["crd"],"application/x-msclip":["clp"],"application/x-msdos-program":["*exe"],"application/x-msdownload":["*exe","*dll","com","bat","*msi"],"application/x-msmediaview":["mvb","m13","m14"],"application/x-msmetafile":["*wmf","*wmz","*emf","emz"],"application/x-msmoney":["mny"],"application/x-mspublisher":["pub"],"application/x-msschedule":["scd"],"application/x-msterminal":["trm"],"application/x-mswrite":["wri"],"application/x-netcdf":["nc","cdf"],"application/x-ns-proxy-autoconfig":["pac"],"application/x-nzb":["nzb"],"application/x-perl":["pl","pm"],"application/x-pilot":["*prc","*pdb"],"application/x-pkcs12":["p12","pfx"],"application/x-pkcs7-certificates":["p7b","spc"],"application/x-pkcs7-certreqresp":["p7r"],"application/x-rar-compressed":["*rar"],"application/x-redhat-package-manager":["rpm"],"application/x-research-info-systems":["ris"],"application/x-sea":["sea"],"application/x-sh":["sh"],"application/x-shar":["shar"],"application/x-shockwave-flash":["swf"],"application/x-silverlight-app":["xap"],"application/x-sql":["sql"],"application/x-stuffit":["sit"],"application/x-stuffitx":["sitx"],"application/x-subrip":["srt"],"application/x-sv4cpio":["sv4cpio"],"application/x-sv4crc":["sv4crc"],"application/x-t3vm-image":["t3"],"application/x-tads":["gam"],"application/x-tar":["tar"],"application/x-tcl":["tcl","tk"],"application/x-tex":["tex"],"application/x-tex-tfm":["tfm"],"application/x-texinfo":["texinfo","texi"],"application/x-tgif":["*obj"],"application/x-ustar":["ustar"],"application/x-virtualbox-hdd":["hdd"],"application/x-virtualbox-ova":["ova"],"application/x-virtualbox-ovf":["ovf"],"application/x-virtualbox-vbox":["vbox"],"application/x-virtualbox-vbox-extpack":["vbox-extpack"],"application/x-virtualbox-vdi":["vdi"],"application/x-virtualbox-vhd":["vhd"],"application/x-virtualbox-vmdk":["vmdk"],"application/x-wais-source":["src"],"application/x-web-app-manifest+json":["webapp"],"application/x-x509-ca-cert":["der","crt","pem"],"application/x-xfig":["fig"],"application/x-xliff+xml":["*xlf"],"application/x-xpinstall":["xpi"],"application/x-xz":["xz"],"application/x-zmachine":["z1","z2","z3","z4","z5","z6","z7","z8"],"audio/vnd.dece.audio":["uva","uvva"],"audio/vnd.digital-winds":["eol"],"audio/vnd.dra":["dra"],"audio/vnd.dts":["dts"],"audio/vnd.dts.hd":["dtshd"],"audio/vnd.lucent.voice":["lvp"],"audio/vnd.ms-playready.media.pya":["pya"],"audio/vnd.nuera.ecelp4800":["ecelp4800"],"audio/vnd.nuera.ecelp7470":["ecelp7470"],"audio/vnd.nuera.ecelp9600":["ecelp9600"],"audio/vnd.rip":["rip"],"audio/x-aac":["aac"],"audio/x-aiff":["aif","aiff","aifc"],"audio/x-caf":["caf"],"audio/x-flac":["flac"],"audio/x-m4a":["*m4a"],"audio/x-matroska":["mka"],"audio/x-mpegurl":["m3u"],"audio/x-ms-wax":["wax"],"audio/x-ms-wma":["wma"],"audio/x-pn-realaudio":["ram","ra"],"audio/x-pn-realaudio-plugin":["rmp"],"audio/x-realaudio":["*ra"],"audio/x-wav":["*wav"],"chemical/x-cdx":["cdx"],"chemical/x-cif":["cif"],"chemical/x-cmdf":["cmdf"],"chemical/x-cml":["cml"],"chemical/x-csml":["csml"],"chemical/x-xyz":["xyz"],"image/prs.btif":["btif"],"image/prs.pti":["pti"],"image/vnd.adobe.photoshop":["psd"],"image/vnd.airzip.accelerator.azv":["azv"],"image/vnd.dece.graphic":["uvi","uvvi","uvg","uvvg"],"image/vnd.djvu":["djvu","djv"],"image/vnd.dvb.subtitle":["*sub"],"image/vnd.dwg":["dwg"],"image/vnd.dxf":["dxf"],"image/vnd.fastbidsheet":["fbs"],"image/vnd.fpx":["fpx"],"image/vnd.fst":["fst"],"image/vnd.fujixerox.edmics-mmr":["mmr"],"image/vnd.fujixerox.edmics-rlc":["rlc"],"image/vnd.microsoft.icon":["ico"],"image/vnd.ms-dds":["dds"],"image/vnd.ms-modi":["mdi"],"image/vnd.ms-photo":["wdp"],"image/vnd.net-fpx":["npx"],"image/vnd.pco.b16":["b16"],"image/vnd.tencent.tap":["tap"],"image/vnd.valve.source.texture":["vtf"],"image/vnd.wap.wbmp":["wbmp"],"image/vnd.xiff":["xif"],"image/vnd.zbrush.pcx":["pcx"],"image/x-3ds":["3ds"],"image/x-cmu-raster":["ras"],"image/x-cmx":["cmx"],"image/x-freehand":["fh","fhc","fh4","fh5","fh7"],"image/x-icon":["*ico"],"image/x-jng":["jng"],"image/x-mrsid-image":["sid"],"image/x-ms-bmp":["*bmp"],"image/x-pcx":["*pcx"],"image/x-pict":["pic","pct"],"image/x-portable-anymap":["pnm"],"image/x-portable-bitmap":["pbm"],"image/x-portable-graymap":["pgm"],"image/x-portable-pixmap":["ppm"],"image/x-rgb":["rgb"],"image/x-tga":["tga"],"image/x-xbitmap":["xbm"],"image/x-xpixmap":["xpm"],"image/x-xwindowdump":["xwd"],"message/vnd.wfa.wsc":["wsc"],"model/vnd.collada+xml":["dae"],"model/vnd.dwf":["dwf"],"model/vnd.gdl":["gdl"],"model/vnd.gtw":["gtw"],"model/vnd.mts":["mts"],"model/vnd.opengex":["ogex"],"model/vnd.parasolid.transmit.binary":["x_b"],"model/vnd.parasolid.transmit.text":["x_t"],"model/vnd.sap.vds":["vds"],"model/vnd.usdz+zip":["usdz"],"model/vnd.valve.source.compiled-map":["bsp"],"model/vnd.vtu":["vtu"],"text/prs.lines.tag":["dsc"],"text/vnd.curl":["curl"],"text/vnd.curl.dcurl":["dcurl"],"text/vnd.curl.mcurl":["mcurl"],"text/vnd.curl.scurl":["scurl"],"text/vnd.dvb.subtitle":["sub"],"text/vnd.fly":["fly"],"text/vnd.fmi.flexstor":["flx"],"text/vnd.graphviz":["gv"],"text/vnd.in3d.3dml":["3dml"],"text/vnd.in3d.spot":["spot"],"text/vnd.sun.j2me.app-descriptor":["jad"],"text/vnd.wap.wml":["wml"],"text/vnd.wap.wmlscript":["wmls"],"text/x-asm":["s","asm"],"text/x-c":["c","cc","cxx","cpp","h","hh","dic"],"text/x-component":["htc"],"text/x-fortran":["f","for","f77","f90"],"text/x-handlebars-template":["hbs"],"text/x-java-source":["java"],"text/x-lua":["lua"],"text/x-markdown":["mkd"],"text/x-nfo":["nfo"],"text/x-opml":["opml"],"text/x-org":["*org"],"text/x-pascal":["p","pas"],"text/x-processing":["pde"],"text/x-sass":["sass"],"text/x-scss":["scss"],"text/x-setext":["etx"],"text/x-sfv":["sfv"],"text/x-suse-ymp":["ymp"],"text/x-uuencode":["uu"],"text/x-vcalendar":["vcs"],"text/x-vcard":["vcf"],"video/vnd.dece.hd":["uvh","uvvh"],"video/vnd.dece.mobile":["uvm","uvvm"],"video/vnd.dece.pd":["uvp","uvvp"],"video/vnd.dece.sd":["uvs","uvvs"],"video/vnd.dece.video":["uvv","uvvv"],"video/vnd.dvb.file":["dvb"],"video/vnd.fvt":["fvt"],"video/vnd.mpegurl":["mxu","m4u"],"video/vnd.ms-playready.media.pyv":["pyv"],"video/vnd.uvvu.mp4":["uvu","uvvu"],"video/vnd.vivo":["viv"],"video/x-f4v":["f4v"],"video/x-fli":["fli"],"video/x-flv":["flv"],"video/x-m4v":["m4v"],"video/x-matroska":["mkv","mk3d","mks"],"video/x-mng":["mng"],"video/x-ms-asf":["asf","asx"],"video/x-ms-vob":["vob"],"video/x-ms-wm":["wm"],"video/x-ms-wmv":["wmv"],"video/x-ms-wmx":["wmx"],"video/x-ms-wvx":["wvx"],"video/x-msvideo":["avi"],"video/x-sgi-movie":["movie"],"video/x-smv":["smv"],"x-conference/x-cooltalk":["ice"]}})),Tt=F(((t,e)=>{var i=zt();e.exports=new i(Et(),Dt())})),At,qt,Le,Ti,Y,ne,Ai,Fe=ce((()=>{var t;At=se(xe()),qt=se(Tt()),Le=se(pe()),Ti=new Le.Token("@jupyterlite/contents:IContents"),(t=Y||(Y={})).JSON="application/json",t.PLAIN_TEXT="text/plain",t.OCTET_STREAM="octet/stream",function(t){let e=JSON.parse(At.PageConfig.getOption("fileTypes")||"{}");t.getType=function(t,i=null){t=t.toLowerCase();for(let i of Object.values(e))for(let e of i.extensions||[])if(e===t&&i.mimeTypes&&i.mimeTypes.length)return i.mimeTypes[0];return qt.default.getType(t)||i||Y.OCTET_STREAM},t.hasFormat=function(t,i){t=t.toLowerCase();for(let a of Object.values(e))if(a.fileFormat===i)for(let e of a.extensions||[])if(e===t)return!0;return!1}}(ne||(ne={})),Ai=new Le.Token("@jupyterlite/contents:IBroadcastChannelWrapper")})),oe,X,Lt,Ut,Nt,Be,Se,Ft=ce((()=>{oe=se(xe()),X=se(xe()),Fe(),Lt=se(pe()),Ut="JupyterLite Storage",Nt=5,Be=class{constructor(t){this.reduceBytesToString=(t,e)=>t+String.fromCharCode(e),this._serverContents=new Map,this._storageName=Ut,this._storageDrivers=null,this._localforage=t.localforage,this._storageName=t.storageName||Ut,this._storageDrivers=t.storageDrivers||null,this._ready=new Lt.PromiseDelegate}async initialize(){await this.initStorage(),this._ready.resolve(void 0)}async initStorage(){this._storage=this.createDefaultStorage(),this._counters=this.createDefaultCounters(),this._checkpoints=this.createDefaultCheckpoints()}get ready(){return this._ready.promise}get storage(){return this.ready.then((()=>this._storage))}get counters(){return this.ready.then((()=>this._counters))}get checkpoints(){return this.ready.then((()=>this._checkpoints))}get defaultStorageOptions(){let t=this._storageDrivers&&this._storageDrivers.length?this._storageDrivers:null;return{version:1,name:this._storageName,...t?{driver:t}:{}}}createDefaultStorage(){return this._localforage.createInstance({description:"Offline Storage for Notebooks and Files",storeName:"files",...this.defaultStorageOptions})}createDefaultCounters(){return this._localforage.createInstance({description:"Store the current file suffix counters",storeName:"counters",...this.defaultStorageOptions})}createDefaultCheckpoints(){return this._localforage.createInstance({description:"Offline Storage for Checkpoints",storeName:"checkpoints",...this.defaultStorageOptions})}async newUntitled(t){var e,i,a;let n,o=null!==(e=null==t?void 0:t.path)&&void 0!==e?e:"",l=null!==(i=null==t?void 0:t.type)&&void 0!==i?i:"notebook",r=(new Date).toISOString(),p=X.PathExt.dirname(o),s=X.PathExt.basename(o),c=X.PathExt.extname(o),d=await this.get(p),m="";switch(o&&!c&&d?(p=`${o}/`,m=""):p&&s?(p=`${p}/`,m=s):(p="",m=o),l){case"directory":m=`Untitled Folder${await this._incrementCounter("directory")||""}`,n={name:m,path:`${p}${m}`,last_modified:r,created:r,format:"json",mimetype:"",content:null,size:0,writable:!0,type:"directory"};break;case"notebook":{let t=await this._incrementCounter("notebook");m=m||`Untitled${t||""}.ipynb`,n={name:m,path:`${p}${m}`,last_modified:r,created:r,format:"json",mimetype:Y.JSON,content:Se.EMPTY_NB,size:JSON.stringify(Se.EMPTY_NB).length,writable:!0,type:"notebook"};break}default:{let e,i=null!==(a=null==t?void 0:t.ext)&&void 0!==a?a:".txt",o=await this._incrementCounter("file"),l=ne.getType(i)||Y.OCTET_STREAM;e=ne.hasFormat(i,"text")||-1!==l.indexOf("text")?"text":-1!==i.indexOf("json")||-1!==i.indexOf("ipynb")?"json":"base64",m=m||`untitled${o||""}${i}`,n={name:m,path:`${p}${m}`,last_modified:r,created:r,format:e,mimetype:l,content:"",size:0,writable:!0,type:"file"};break}}let u=n.path;return await(await this.storage).setItem(u,n),n}async copy(t,e){let i=X.PathExt.basename(t);for(e=""===e?"":`${e.slice(1)}/`;await this.get(`${e}${i}`,{content:!0});){let t=X.PathExt.extname(i);i=`${i.replace(t,"")} (copy)${t}`}let a=`${e}${i}`,n=await this.get(t,{content:!0});if(!n)throw Error(`Could not find file with path ${t}`);return n={...n,name:i,path:a},await(await this.storage).setItem(a,n),n}async get(t,e){if(""===(t=decodeURIComponent(t.replace(/^\//,""))))return await this._getFolder(t);let i=await this.storage,a=await i.getItem(t),n=await this._getServerContents(t,e),o=a||n;if(!o)return null;if(null==e||!e.content)return{size:0,...o,content:null};if("directory"===o.type){let e=new Map;await i.iterate(((i,a)=>{a===`${t}/${i.name}`&&e.set(i.name,i)}));let a=n?n.content:Array.from((await this._getServerDirectory(t)).values());for(let t of a)e.has(t.name)||e.set(t.name,t);let l=[...e.values()];return{name:X.PathExt.basename(t),path:t,last_modified:o.last_modified,created:o.created,format:"json",mimetype:Y.JSON,content:l,size:0,writable:!0,type:"directory"}}return o}async rename(t,e){let i=decodeURIComponent(t),a=await this.get(i,{content:!0});if(!a)throw Error(`Could not find file with path ${i}`);let n=(new Date).toISOString(),o=X.PathExt.basename(e),l={...a,name:o,path:e,last_modified:n},r=await this.storage;if(await r.setItem(e,l),await r.removeItem(i),await(await this.checkpoints).removeItem(i),"directory"===a.type){let i;for(i of a.content)await this.rename(oe.URLExt.join(t,i.name),oe.URLExt.join(e,i.name))}return l}async save(t,e={}){var i;t=decodeURIComponent(t);let a=X.PathExt.extname(null!==(i=e.name)&&void 0!==i?i:""),n=e.chunk,o=!!n&&(n>1||-1===n),l=await this.get(t,{content:o});if(l||(l=await this.newUntitled({path:t,ext:a,type:"file"})),!l)return null;let r=l.content,p=(new Date).toISOString();if(l={...l,...e,last_modified:p},e.content&&"base64"===e.format){let t=!n||-1===n;if(".ipynb"===a){let i=this._handleChunk(e.content,r,o);l={...l,content:t?JSON.parse(i):i,format:"json",type:"notebook",size:i.length}}else if(ne.hasFormat(a,"json")){let i=this._handleChunk(e.content,r,o);l={...l,content:t?JSON.parse(i):i,format:"json",type:"file",size:i.length}}else if(ne.hasFormat(a,"text")){let t=this._handleChunk(e.content,r,o);l={...l,content:t,format:"text",type:"file",size:t.length}}else{let t=e.content;l={...l,content:t,size:atob(t).length}}}return await(await this.storage).setItem(t,l),l}async delete(t){let e=`${t=decodeURIComponent(t)}/`,i=(await(await this.storage).keys()).filter((i=>i===t||i.startsWith(e)));await Promise.all(i.map(this.forgetPath,this))}async forgetPath(t){await Promise.all([(await this.storage).removeItem(t),(await this.checkpoints).removeItem(t)])}async createCheckpoint(t){var e;let i=await this.checkpoints;t=decodeURIComponent(t);let a=await this.get(t,{content:!0});if(!a)throw Error(`Could not find file with path ${t}`);let n=(null!==(e=await i.getItem(t))&&void 0!==e?e:[]).filter(Boolean);return n.push(a),n.length>Nt&&n.splice(0,n.length-Nt),await i.setItem(t,n),{id:""+(n.length-1),last_modified:a.last_modified}}async listCheckpoints(t){return(await(await this.checkpoints).getItem(t)||[]).filter(Boolean).map(this.normalizeCheckpoint,this)}normalizeCheckpoint(t,e){return{id:e.toString(),last_modified:t.last_modified}}async restoreCheckpoint(t,e){t=decodeURIComponent(t);let i=(await(await this.checkpoints).getItem(t)||[])[parseInt(e)];await(await this.storage).setItem(t,i)}async deleteCheckpoint(t,e){t=decodeURIComponent(t);let i=await(await this.checkpoints).getItem(t)||[],a=parseInt(e);i.splice(a,1),await(await this.checkpoints).setItem(t,i)}_handleChunk(t,e,i){let a=decodeURIComponent(escape(atob(t)));return i?e+a:a}async _getFolder(t){let e=new Map;await(await this.storage).iterate(((t,i)=>{i.includes("/")||e.set(t.path,t)}));for(let i of(await this._getServerDirectory(t)).values())e.has(i.path)||e.set(i.path,i);return t&&0===e.size?null:{name:"",path:t,last_modified:new Date(0).toISOString(),created:new Date(0).toISOString(),format:"json",mimetype:Y.JSON,content:Array.from(e.values()),size:0,writable:!0,type:"directory"}}async _getServerContents(t,e){let i=X.PathExt.basename(t),a=(await this._getServerDirectory(oe.URLExt.join(t,".."))).get(i);if(!a)return null;if(a=a||{name:i,path:t,last_modified:new Date(0).toISOString(),created:new Date(0).toISOString(),format:"text",mimetype:Y.PLAIN_TEXT,type:"file",writable:!0,size:0,content:""},null!=e&&e.content)if("directory"===a.type){let e=await this._getServerDirectory(t);a={...a,content:Array.from(e.values())}}else{let e=oe.URLExt.join(oe.PageConfig.getBaseUrl(),"files",t),n=await fetch(e);if(!n.ok)return null;let o=a.mimetype||n.headers.get("Content-Type"),l=X.PathExt.extname(i);if("notebook"===a.type||ne.hasFormat(l,"json")||-1!==(null==o?void 0:o.indexOf("json"))||t.match(/\.(ipynb|[^/]*json[^/]*)$/)){let t=await n.text();a={...a,content:JSON.parse(t),format:"json",mimetype:a.mimetype||Y.JSON,size:t.length}}else if(ne.hasFormat(l,"text")||-1!==o.indexOf("text")){let t=await n.text();a={...a,content:t,format:"text",mimetype:o||Y.PLAIN_TEXT,size:t.length}}else{let t=await n.arrayBuffer(),e=new Uint8Array(t);a={...a,content:btoa(e.reduce(this.reduceBytesToString,"")),format:"base64",mimetype:o||Y.OCTET_STREAM,size:e.length}}}return a}async _getServerDirectory(t){let e=this._serverContents.get(t)||new Map;if(!this._serverContents.has(t)){let i=oe.URLExt.join(oe.PageConfig.getBaseUrl(),"api/contents",t,"all.json");try{let t=await fetch(i),a=JSON.parse(await t.text());for(let t of a.content)e.set(t.name,t)}catch(t){console.warn(`don't worry, about ${t}... nothing's broken. If there had been a\n file at ${i}, you might see some more files.`)}this._serverContents.set(t,e)}return e}async _incrementCounter(t){var e;let i=await this.counters,a=(null!==(e=await i.getItem(t))&&void 0!==e?e:-1)+1;return await i.setItem(t,a),a}},(Se||(Se={})).EMPTY_NB={metadata:{orig_nbformat:4},nbformat_minor:4,nbformat:4,cells:[]}})),ze,Bt,qi,Ui,$t=ce((()=>{ze=16895,Bt=33206,qi=1,Ui=2})),Wt,He,De,Ni,Li,Ht,Re,Ee,Ie,$e,We=ce((()=>{Wt=":",He="/api/drive.v1",De=4096,Ni=new TextEncoder,Li=new TextDecoder("utf-8"),Ht={0:!1,1:!0,2:!0,64:!0,65:!0,66:!0,129:!0,193:!0,514:!0,577:!0,578:!0,705:!0,706:!0,1024:!0,1025:!0,1026:!0,1089:!0,1090:!0,1153:!0,1154:!0,1217:!0,1218:!0,4096:!0,4098:!0},Re=class{constructor(t){this.fs=t}open(t){let e=this.fs.realPath(t.node);this.fs.FS.isFile(t.node.mode)&&(t.file=this.fs.API.get(e))}close(t){if(!this.fs.FS.isFile(t.node.mode)||!t.file)return;let e=this.fs.realPath(t.node),i=t.flags,a="string"==typeof i?parseInt(i,10):i;a&=8191;let n=!0;a in Ht&&(n=Ht[a]),n&&this.fs.API.put(e,t.file),t.file=void 0}read(t,e,i,a,n){if(a<=0||void 0===t.file||n>=(t.file.data.length||0))return 0;let o=Math.min(t.file.data.length-n,a);return e.set(t.file.data.subarray(n,n+o),i),o}write(t,e,i,a,n){var o;if(a<=0||void 0===t.file)return 0;if(t.node.timestamp=Date.now(),n+a>((null===(o=t.file)||void 0===o?void 0:o.data.length)||0)){let e=t.file.data?t.file.data:new Uint8Array;t.file.data=new Uint8Array(n+a),t.file.data.set(e)}return t.file.data.set(e.subarray(i,i+a),n),a}llseek(t,e,i){let a=e;if(1===i)a+=t.position;else if(2===i&&this.fs.FS.isFile(t.node.mode)){if(void 0===t.file)throw new this.fs.FS.ErrnoError(this.fs.ERRNO_CODES.EPERM);a+=t.file.data.length}if(a<0)throw new this.fs.FS.ErrnoError(this.fs.ERRNO_CODES.EINVAL);return a}},Ee=class{constructor(t){this.fs=t}getattr(t){return{...this.fs.API.getattr(this.fs.realPath(t)),mode:t.mode,ino:t.id}}setattr(t,e){for(let[i,a]of Object.entries(e))switch(i){case"mode":t.mode=a;break;case"timestamp":t.timestamp=a;break;default:console.warn("setattr",i,"of",a,"on",t,"not yet implemented")}}lookup(t,e){let i=this.fs.PATH.join2(this.fs.realPath(t),e),a=this.fs.API.lookup(i);if(!a.ok)throw this.fs.FS.genericErrors[this.fs.ERRNO_CODES.ENOENT];return this.fs.createNode(t,e,a.mode,0)}mknod(t,e,i,a){let n=this.fs.PATH.join2(this.fs.realPath(t),e);return this.fs.API.mknod(n,i),this.fs.createNode(t,e,i,a)}rename(t,e,i){this.fs.API.rename(t.parent?this.fs.PATH.join2(this.fs.realPath(t.parent),t.name):t.name,this.fs.PATH.join2(this.fs.realPath(e),i)),t.name=i,t.parent=e}unlink(t,e){this.fs.API.rmdir(this.fs.PATH.join2(this.fs.realPath(t),e))}rmdir(t,e){this.fs.API.rmdir(this.fs.PATH.join2(this.fs.realPath(t),e))}readdir(t){return this.fs.API.readdir(this.fs.realPath(t))}symlink(t,e,i){throw new this.fs.FS.ErrnoError(this.fs.ERRNO_CODES.EPERM)}readlink(t){throw new this.fs.FS.ErrnoError(this.fs.ERRNO_CODES.EPERM)}},Ie=class{constructor(t,e,i,a,n){this._baseUrl=t,this._driveName=e,this._mountpoint=i,this.FS=a,this.ERRNO_CODES=n}request(t){let e=new XMLHttpRequest;e.open("POST",encodeURI(this.endpoint),!1);try{e.send(JSON.stringify(t))}catch(t){console.error(t)}if(e.status>=400)throw new this.FS.ErrnoError(this.ERRNO_CODES.EINVAL);return JSON.parse(e.responseText)}lookup(t){return this.request({method:"lookup",path:this.normalizePath(t)})}getmode(t){return Number.parseInt(this.request({method:"getmode",path:this.normalizePath(t)}))}mknod(t,e){return this.request({method:"mknod",path:this.normalizePath(t),data:{mode:e}})}rename(t,e){return this.request({method:"rename",path:this.normalizePath(t),data:{newPath:this.normalizePath(e)}})}readdir(t){let e=this.request({method:"readdir",path:this.normalizePath(t)});return e.push("."),e.push(".."),e}rmdir(t){return this.request({method:"rmdir",path:this.normalizePath(t)})}get(t){let e=this.request({method:"get",path:this.normalizePath(t)}),i=e.content,a=e.format;switch(a){case"json":case"text":return{data:Ni.encode(i),format:a};case"base64":{let t=atob(i),e=t.length,n=new Uint8Array(e);for(let i=0;i{Ke=se(xe()),We(),Je=class{constructor(t){this.isDisposed=!1,this._onMessage=async t=>{if(!this._channel)return;let{_contents:e}=this,i=t.data,a=null==i?void 0:i.path;if("broadcast.ts"!==(null==i?void 0:i.receiver))return;let n,o=null;switch(null==i?void 0:i.method){case"readdir":n=await e.get(a,{content:!0}),o=[],"directory"===n.type&&n.content&&(o=n.content.map((t=>t.name)));break;case"rmdir":await e.delete(a);break;case"rename":await e.rename(a,i.data.newPath);break;case"getmode":n=await e.get(a),o="directory"===n.type?16895:33206;break;case"lookup":try{n=await e.get(a),o={ok:!0,mode:"directory"===n.type?16895:33206}}catch{o={ok:!1}}break;case"mknod":n=await e.newUntitled({path:Ke.PathExt.dirname(a),type:16895===Number.parseInt(i.data.mode)?"directory":"file",ext:Ke.PathExt.extname(a)}),await e.rename(n.path,a);break;case"getattr":{n=await e.get(a);let t=new Date(0).toISOString();o={dev:1,nlink:1,uid:0,gid:0,rdev:0,size:n.size||0,blksize:De,blocks:Math.ceil(n.size||0/De),atime:n.last_modified||t,mtime:n.last_modified||t,ctime:n.created||t,timestamp:0};break}case"get":if(n=await e.get(a,{content:!0}),"directory"===n.type)break;o={content:"json"===n.format?JSON.stringify(n.content):n.content,format:n.format};break;case"put":await e.save(a,{content:"json"===i.data.format?JSON.parse(i.data.data):i.data.data,type:"file",format:i.data.format});break;default:o=null}this._channel.postMessage(o)},this._channel=null,this._enabled=!1,this._contents=t.contents}get enabled(){return this._enabled}enable(){this._channel?console.warn("BroadcastChannel already created and enabled"):(this._channel=new BroadcastChannel(He),this._channel.addEventListener("message",this._onMessage),this._enabled=!0)}disable(){this._channel&&(this._channel.removeEventListener("message",this._onMessage),this._channel=null),this._enabled=!1}dispose(){this.isDisposed||(this.disable(),this.isDisposed=!0)}}})),Jt={};li(Jt,{BLOCK_SIZE:()=>De,BroadcastChannelWrapper:()=>Je,Contents:()=>Be,ContentsAPI:()=>Ie,DIR_MODE:()=>ze,DRIVE_API_PATH:()=>He,DRIVE_SEPARATOR:()=>Wt,DriveFS:()=>$e,DriveFSEmscriptenNodeOps:()=>Ee,DriveFSEmscriptenStreamOps:()=>Re,FILE:()=>ne,FILE_MODE:()=>Bt,IBroadcastChannelWrapper:()=>Ai,IContents:()=>Ti,MIME:()=>Y,SEEK_CUR:()=>qi,SEEK_END:()=>Ui});var Vt=ce((()=>{Ft(),We(),Fe(),Kt(),$t()})),Yt=class{constructor(){this._options=null,this._initializer=null,this._pyodide=null,this._localPath="",this._driveName="",this._driveFS=null,this._initialized=new Promise(((t,e)=>{this._initializer={resolve:t,reject:e}}))}async initialize(t){var e;if(this._options=t,t.location.includes(":")){let e=t.location.split(":");this._driveName=e[0],this._localPath=e[1]}else this._driveName="",this._localPath=t.location;await this.initRuntime(t),await this.initFilesystem(t),await this.initPackageManager(t),await this.initKernel(t),await this.initGlobals(t),null==(e=this._initializer)||e.resolve()}async initRuntime(t){let e,{pyodideUrl:i,indexUrl:a}=t;i.endsWith(".mjs")?e=(await __webpack_require__(265)(i)).loadPyodide:(importScripts(i),e=self.loadPyodide),this._pyodide=await e({indexURL:a})}async initPackageManager(t){if(!this._options)throw new Error("Uninitialized");let{pipliteWheelUrl:e,disablePyPIFallback:i,pipliteUrls:a}=this._options;await this._pyodide.loadPackage(["micropip"]),await this._pyodide.runPythonAsync(`\n import micropip\n await micropip.install('${e}', keep_going=True)\n import piplite.piplite\n piplite.piplite._PIPLITE_DISABLE_PYPI = ${i?"True":"False"}\n piplite.piplite._PIPLITE_URLS = ${JSON.stringify(a)}\n `)}async initKernel(t){await this._pyodide.runPythonAsync("\n await piplite.install(['sqlite3'], keep_going=True);\n await piplite.install(['ipykernel'], keep_going=True);\n await piplite.install(['comm'], keep_going=True);\n await piplite.install(['pyodide_kernel'], keep_going=True);\n await piplite.install(['ipython'], keep_going=True);\n import pyodide_kernel\n "),t.mountDrive&&this._localPath&&await this._pyodide.runPythonAsync(`\n import os;\n os.chdir("${this._localPath}");\n `)}async initGlobals(t){let{globals:e}=this._pyodide;this._kernel=e.get("pyodide_kernel").kernel_instance.copy(),this._stdout_stream=e.get("pyodide_kernel").stdout_stream.copy(),this._stderr_stream=e.get("pyodide_kernel").stderr_stream.copy(),this._interpreter=this._kernel.interpreter.copy(),this._interpreter.send_comm=this.sendComm.bind(this)}async initFilesystem(t){if(t.mountDrive){let e="/drive",{FS:i,PATH:a,ERRNO_CODES:n}=this._pyodide,{baseUrl:o}=t,{DriveFS:l}=await Promise.resolve().then((()=>(Vt(),Jt))),r=new l({FS:i,PATH:a,ERRNO_CODES:n,baseUrl:o,driveName:this._driveName,mountpoint:e});i.mkdir(e),i.mount(r,{},e),i.chdir(e),this._driveFS=r}}mapToObject(t){let e=t instanceof Array?[]:{};return t.forEach(((t,i)=>{e[i]=t instanceof Map||t instanceof Array?this.mapToObject(t):t})),e}formatResult(t){if(!(t instanceof this._pyodide.ffi.PyProxy))return t;let e=t.toJs();return this.mapToObject(e)}async setup(t){await this._initialized,this._kernel._parent_header=this._pyodide.toPy(t)}async execute(t,e){await this.setup(e);let i=(t,e)=>{let i={name:this.formatResult(t),text:this.formatResult(e)};postMessage({parentHeader:this.formatResult(this._kernel._parent_header).header,bundle:i,type:"stream"})};this._stdout_stream.publish_stream_callback=i,this._stderr_stream.publish_stream_callback=i,this._interpreter.display_pub.clear_output_callback=t=>{let e={wait:this.formatResult(t)};postMessage({parentHeader:this.formatResult(this._kernel._parent_header).header,bundle:e,type:"clear_output"})},this._interpreter.display_pub.display_data_callback=(t,e,i)=>{let a={data:this.formatResult(t),metadata:this.formatResult(e),transient:this.formatResult(i)};postMessage({parentHeader:this.formatResult(this._kernel._parent_header).header,bundle:a,type:"display_data"})},this._interpreter.display_pub.update_display_data_callback=(t,e,i)=>{let a={data:this.formatResult(t),metadata:this.formatResult(e),transient:this.formatResult(i)};postMessage({parentHeader:this.formatResult(this._kernel._parent_header).header,bundle:a,type:"update_display_data"})},this._interpreter.displayhook.publish_execution_result=(t,e,i)=>{let a={execution_count:t,data:this.formatResult(e),metadata:this.formatResult(i)};postMessage({parentHeader:this.formatResult(this._kernel._parent_header).header,bundle:a,type:"execute_result"})},this._interpreter.input=this.input.bind(this),this._interpreter.getpass=this.getpass.bind(this);let a=await this._kernel.run(t.code),n=this.formatResult(a);return"error"===n.status&&((t,e,i)=>{let a={ename:t,evalue:e,traceback:i};postMessage({parentHeader:this.formatResult(this._kernel._parent_header).header,bundle:a,type:"execute_error"})})(n.ename,n.evalue,n.traceback),n}async complete(t,e){await this.setup(e);let i=this._kernel.complete(t.code,t.cursor_pos);return this.formatResult(i)}async inspect(t,e){await this.setup(e);let i=this._kernel.inspect(t.code,t.cursor_pos,t.detail_level);return this.formatResult(i)}async isComplete(t,e){await this.setup(e);let i=this._kernel.is_complete(t.code);return this.formatResult(i)}async commInfo(t,e){await this.setup(e);let i=this._kernel.comm_info(t.target_name);return{comms:this.formatResult(i),status:"ok"}}async commOpen(t,e){await this.setup(e);let i=this._kernel.comm_manager.comm_open(this._pyodide.toPy(null),this._pyodide.toPy(null),this._pyodide.toPy(t));return this.formatResult(i)}async commMsg(t,e){await this.setup(e);let i=this._kernel.comm_manager.comm_msg(this._pyodide.toPy(null),this._pyodide.toPy(null),this._pyodide.toPy(t));return this.formatResult(i)}async commClose(t,e){await this.setup(e);let i=this._kernel.comm_manager.comm_close(this._pyodide.toPy(null),this._pyodide.toPy(null),this._pyodide.toPy(t));return this.formatResult(i)}async inputReply(t,e){await this.setup(e),this._resolveInputReply(t)}async sendInputRequest(t,e){let i={prompt:t,password:e};postMessage({type:"input_request",parentHeader:this.formatResult(this._kernel._parent_header).header,content:i})}async getpass(t){return t=void 0===t?"":t,await this.sendInputRequest(t,!0),(await new Promise((t=>{this._resolveInputReply=t}))).value}async input(t){return t=void 0===t?"":t,await this.sendInputRequest(t,!1),(await new Promise((t=>{this._resolveInputReply=t}))).value}async sendComm(t,e,i,a,n){postMessage({type:t,content:this.formatResult(e),metadata:this.formatResult(i),ident:this.formatResult(a),buffers:this.formatResult(n),parentHeader:this.formatResult(this._kernel._parent_header).header})}}}}]);
+//# sourceMappingURL=296.thebe-lite.min.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/296.thebe-lite.min.js.map b/book/_build/html/_static/296.thebe-lite.min.js.map
new file mode 100644
index 0000000..c0e853c
--- /dev/null
+++ b/book/_build/html/_static/296.thebe-lite.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"296.thebe-lite.min.js","mappings":"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","sources":["webpack://thebe-lite/./node_modules/@jupyterlite/pyodide-kernel/lib/worker.js"],"sourcesContent":["var ni=Object.create;var Me=Object.defineProperty;var ai=Object.getOwnPropertyDescriptor;var oi=Object.getOwnPropertyNames;var si=Object.getPrototypeOf,ri=Object.prototype.hasOwnProperty;var ce=(n,e)=>()=>(n&&(e=n(n=0)),e);var F=(n,e)=>()=>(e||n((e={exports:{}}).exports,e),e.exports),li=(n,e)=>{for(var t in e)Me(n,t,{get:e[t],enumerable:!0})},ci=(n,e,t,i)=>{if(e&&typeof e==\"object\"||typeof e==\"function\")for(let a of oi(e))!ri.call(n,a)&&a!==t&&Me(n,a,{get:()=>e[a],enumerable:!(i=ai(e,a))||i.enumerable});return n};var se=(n,e,t)=>(t=n!=null?ni(si(n)):{},ci(e||!n||!n.__esModule?Me(t,\"default\",{value:n,enumerable:!0}):t,n));var Ye=F((be,Ve)=>{(function(n,e){typeof be==\"object\"&&typeof Ve!=\"undefined\"?e(be):typeof define==\"function\"&&define.amd?define([\"exports\"],e):(n=typeof globalThis!=\"undefined\"?globalThis:n||self,e(n.lumino_algorithm={}))})(be,function(n){\"use strict\";n.ArrayExt=void 0,function(u){function v(g,w,d=0,p=-1){let f=g.length;if(f===0)return-1;d<0?d=Math.max(0,d+f):d=Math.min(d,f-1),p<0?p=Math.max(0,p+f):p=Math.min(p,f-1);let _;p0;){let Z=U>>1,fe=k+Z;d(g[fe],w)<0?(k=fe+1,U-=Z+1):U=Z}return k}u.lowerBound=A;function H(g,w,d,p=0,f=-1){let _=g.length;if(_===0)return 0;p<0?p=Math.max(0,p+_):p=Math.min(p,_-1),f<0?f=Math.max(0,f+_):f=Math.min(f,_-1);let k=p,U=f-p+1;for(;U>0;){let Z=U>>1,fe=k+Z;d(g[fe],w)>0?U=Z:(k=fe+1,U-=Z+1)}return k}u.upperBound=H;function L(g,w,d){if(g===w)return!0;if(g.length!==w.length)return!1;for(let p=0,f=g.length;p=_&&(d=f<0?_-1:_),p===void 0?p=f<0?-1:_:p<0?p=Math.max(p+_,f<0?-1:0):p>=_&&(p=f<0?_-1:_);let k;f<0&&p>=d||f>0&&d>=p?k=0:f<0?k=Math.floor((p-d+1)/f+1):k=Math.floor((p-d-1)/f+1);let U=[];for(let Z=0;Z=p))return;let _=p-d+1;if(w>0?w=w%_:w<0&&(w=(w%_+_)%_),w===0)return;let k=d+w;K(g,d,k-1),K(g,k,p),K(g,d,p)}u.rotate=G;function Q(g,w,d=0,p=-1){let f=g.length;if(f===0)return;d<0?d=Math.max(0,d+f):d=Math.min(d,f-1),p<0?p=Math.max(0,p+f):p=Math.min(p,f-1);let _;pw;--f)g[f]=g[f-1];g[w]=d}u.insert=Zt;function me(g,w){let d=g.length;if(w<0&&(w+=d),w<0||w>=d)return;let p=g[w];for(let f=w+1;f=d&&k<=p&&g[k]===w||p=d)&&g[k]===w?_++:_>0&&(g[k-_]=g[k]);return _>0&&(g.length=f-_),_}u.removeAllOf=Qt;function ei(g,w,d=0,p=-1){let f,_=y(g,w,d,p);return _!==-1&&(f=me(g,_)),{index:_,value:f}}u.removeFirstWhere=ei;function ti(g,w,d=-1,p=0){let f,_=M(g,w,d,p);return _!==-1&&(f=me(g,_)),{index:_,value:f}}u.removeLastWhere=ti;function ii(g,w,d=0,p=-1){let f=g.length;if(f===0)return 0;d<0?d=Math.max(0,d+f):d=Math.min(d,f-1),p<0?p=Math.max(0,p+f):p=Math.min(p,f-1);let _=0;for(let k=0;k=d&&k<=p&&w(g[k],k)||p=d)&&w(g[k],k)?_++:_>0&&(g[k-_]=g[k]);return _>0&&(g.length=f-_),_}u.removeAllWhere=ii}(n.ArrayExt||(n.ArrayExt={}));function*e(...u){for(let v of u)yield*v}function*t(){}function*i(u,v=0){for(let x of u)yield[v++,x]}function*a(u,v){let x=0;for(let y of u)v(y,x++)&&(yield y)}function o(u,v){let x=0;for(let y of u)if(v(y,x++))return y}function r(u,v){let x=0;for(let y of u)if(v(y,x++))return x-1;return-1}function s(u,v){let x;for(let y of u){if(x===void 0){x=y;continue}v(y,x)<0&&(x=y)}return x}function l(u,v){let x;for(let y of u){if(x===void 0){x=y;continue}v(y,x)>0&&(x=y)}return x}function m(u,v){let x=!0,y,M;for(let B of u)x?(y=B,M=B,x=!1):v(B,y)<0?y=B:v(B,M)>0&&(M=B);return x?void 0:[y,M]}function h(u){return Array.from(u)}function c(u){let v={};for(let[x,y]of u)v[x]=y;return v}function b(u,v){let x=0;for(let y of u)if(v(y,x++)===!1)return}function j(u,v){let x=0;for(let y of u)if(v(y,x++)===!1)return!1;return!0}function C(u,v){let x=0;for(let y of u)if(v(y,x++))return!0;return!1}function*q(u,v){let x=0;for(let y of u)yield v(y,x++)}function*O(u,v,x){v===void 0?(v=u,u=0,x=1):x===void 0&&(x=1);let y=S.rangeLength(u,v,x);for(let M=0;My&&M>0||x-1;v--)yield u[v]}function V(u){let v=[],x=new Set,y=new Map;for(let T of u)M(T);for(let[T]of y)B(T);return v;function M(T){let[A,H]=T,L=y.get(H);L?L.push(A):y.set(H,[A])}function B(T){if(x.has(T))return;x.add(T);let A=y.get(T);if(A)for(let H of A)B(H);v.push(T)}}function*D(u,v){let x=0;for(let y of u)x++%v===0&&(yield y)}n.StringExt=void 0,function(u){function v(T,A,H=0){let L=new Array(A.length);for(let W=0,$=H,K=A.length;WA?1:0}u.cmp=B}(n.StringExt||(n.StringExt={}));function*z(u,v){if(v<1)return;let x=u[Symbol.iterator](),y;for(;0y[Symbol.iterator]()),x=v.map(y=>y.next());for(;j(x,y=>!y.done);x=v.map(y=>y.next()))yield x.map(y=>y.value)}n.chain=e,n.each=b,n.empty=t,n.enumerate=i,n.every=j,n.filter=a,n.find=o,n.findIndex=r,n.map=q,n.max=l,n.min=s,n.minmax=m,n.once=P,n.range=O,n.reduce=R,n.repeat=I,n.retro=N,n.some=C,n.stride=D,n.take=z,n.toArray=h,n.toObject=c,n.topologicSort=V,n.zip=E})});var pe=F((we,Ze)=>{(function(n,e){typeof we==\"object\"&&typeof Ze!=\"undefined\"?e(we):typeof define==\"function\"&&define.amd?define([\"exports\"],e):(n=typeof globalThis!=\"undefined\"?globalThis:n||self,e(n.lumino_coreutils={}))})(we,function(n){\"use strict\";n.JSONExt=void 0,function(r){r.emptyObject=Object.freeze({}),r.emptyArray=Object.freeze([]);function s(O){return O===null||typeof O==\"boolean\"||typeof O==\"number\"||typeof O==\"string\"}r.isPrimitive=s;function l(O){return Array.isArray(O)}r.isArray=l;function m(O){return!s(O)&&!l(O)}r.isObject=m;function h(O,S){if(O===S)return!0;if(s(O)||s(S))return!1;let R=l(O),I=l(S);return R!==I?!1:R&&I?b(O,S):j(O,S)}r.deepEqual=h;function c(O){return s(O)?O:l(O)?C(O):q(O)}r.deepCopy=c;function b(O,S){if(O===S)return!0;if(O.length!==S.length)return!1;for(let R=0,I=O.length;R{this._resolve=s,this._reject=l})}resolve(s){let l=this._resolve;l(s)}reject(s){let l=this._reject;l(s)}}class i{constructor(s,l){this.name=s,this.description=l!=null?l:\"\",this._tokenStructuralPropertyT=null}}function a(r){let s=0;for(let l=0,m=r.length;l>>0),r[l]=s&255,s>>>=8}n.Random=void 0,function(r){r.getRandomValues=(()=>{let s=typeof window!=\"undefined\"&&(window.crypto||window.msCrypto)||null;return s&&typeof s.getRandomValues==\"function\"?function(m){return s.getRandomValues(m)}:a})()}(n.Random||(n.Random={}));function o(r){let s=new Uint8Array(16),l=new Array(256);for(let m=0;m<16;++m)l[m]=\"0\"+m.toString(16);for(let m=16;m<256;++m)l[m]=m.toString(16);return function(){return r(s),s[6]=64|s[6]&15,s[8]=128|s[8]&63,l[s[0]]+l[s[1]]+l[s[2]]+l[s[3]]+\"-\"+l[s[4]]+l[s[5]]+\"-\"+l[s[6]]+l[s[7]]+\"-\"+l[s[8]]+l[s[9]]+\"-\"+l[s[10]]+l[s[11]]+l[s[12]]+l[s[13]]+l[s[14]]+l[s[15]]}}n.UUID=void 0,function(r){r.uuid4=o(n.Random.getRandomValues)}(n.UUID||(n.UUID={})),n.MimeData=e,n.PromiseDelegate=t,n.Token=i})});var Xe=F((ye,Ge)=>{(function(n,e){typeof ye==\"object\"&&typeof Ge!=\"undefined\"?e(ye,Ye(),pe()):typeof define==\"function\"&&define.amd?define([\"exports\",\"@lumino/algorithm\",\"@lumino/coreutils\"],e):(n=typeof globalThis!=\"undefined\"?globalThis:n||self,e(n.lumino_signaling={},n.lumino_algorithm,n.lumino_coreutils))})(ye,function(n,e,t){\"use strict\";class i{constructor(s){this.sender=s}connect(s,l){return o.connect(this,s,l)}disconnect(s,l){return o.disconnect(this,s,l)}emit(s){o.emit(this,s)}}(function(r){function s(C,q){o.disconnectBetween(C,q)}r.disconnectBetween=s;function l(C){o.disconnectSender(C)}r.disconnectSender=l;function m(C){o.disconnectReceiver(C)}r.disconnectReceiver=m;function h(C){o.disconnectAll(C)}r.disconnectAll=h;function c(C){o.disconnectAll(C)}r.clearData=c;function b(){return o.exceptionHandler}r.getExceptionHandler=b;function j(C){let q=o.exceptionHandler;return o.exceptionHandler=C,q}r.setExceptionHandler=j})(i||(i={}));class a extends i{constructor(){super(...arguments),this._pending=new t.PromiseDelegate}async*[Symbol.asyncIterator](){let s=this._pending;for(;;)try{let{args:l,next:m}=await s.promise;s=m,yield l}catch{return}}emit(s){let l=this._pending,m=this._pending=new t.PromiseDelegate;l.resolve({args:s,next:m}),super.emit(s)}stop(){this._pending.promise.catch(()=>{}),this._pending.reject(\"stop\"),this._pending=new t.PromiseDelegate}}var o;(function(r){r.exceptionHandler=z=>{console.error(z)};function s(z,E,u){u=u||void 0;let v=C.get(z.sender);if(v||(v=[],C.set(z.sender,v)),R(v,z,E,u))return!1;let x=u||E,y=q.get(x);y||(y=[],q.set(x,y));let M={signal:z,slot:E,thisArg:u};return v.push(M),y.push(M),!0}r.connect=s;function l(z,E,u){u=u||void 0;let v=C.get(z.sender);if(!v||v.length===0)return!1;let x=R(v,z,E,u);if(!x)return!1;let y=u||E,M=q.get(y);return x.signal=null,P(v),P(M),!0}r.disconnect=l;function m(z,E){let u=C.get(z);if(!u||u.length===0)return;let v=q.get(E);if(!(!v||v.length===0)){for(let x of v)x.signal&&x.signal.sender===z&&(x.signal=null);P(u),P(v)}}r.disconnectBetween=m;function h(z){let E=C.get(z);if(!(!E||E.length===0)){for(let u of E){if(!u.signal)continue;let v=u.thisArg||u.slot;u.signal=null,P(q.get(v))}P(E)}}r.disconnectSender=h;function c(z){let E=q.get(z);if(!(!E||E.length===0)){for(let u of E){if(!u.signal)continue;let v=u.signal.sender;u.signal=null,P(C.get(v))}P(E)}}r.disconnectReceiver=c;function b(z){h(z),c(z)}r.disconnectAll=b;function j(z,E){let u=C.get(z.sender);if(!(!u||u.length===0))for(let v=0,x=u.length;vtypeof requestAnimationFrame==\"function\"?requestAnimationFrame:setImmediate)();function R(z,E,u,v){return e.find(z,x=>x.signal===E&&x.slot===u&&x.thisArg===v)}function I(z,E){let{signal:u,slot:v,thisArg:x}=z;try{v.call(x,u.sender,E)}catch(y){r.exceptionHandler(y)}}function P(z){O.size===0&&S(N),O.add(z)}function N(){O.forEach(V),O.clear()}function V(z){e.ArrayExt.removeAllWhere(z,D)}function D(z){return z.signal===null}})(o||(o={})),n.Signal=i,n.Stream=a})});var et=F(_e=>{\"use strict\";Object.defineProperty(_e,\"__esModule\",{value:!0});_e.ActivityMonitor=void 0;var Qe=Xe(),Te=class{constructor(e){this._timer=-1,this._timeout=-1,this._isDisposed=!1,this._activityStopped=new Qe.Signal(this),e.signal.connect(this._onSignalFired,this),this._timeout=e.timeout||1e3}get activityStopped(){return this._activityStopped}get timeout(){return this._timeout}set timeout(e){this._timeout=e}get isDisposed(){return this._isDisposed}dispose(){this._isDisposed||(this._isDisposed=!0,Qe.Signal.clearData(this))}_onSignalFired(e,t){clearTimeout(this._timer),this._sender=e,this._args=t,this._timer=setTimeout(()=>{this._activityStopped.emit({sender:this._sender,args:this._args})},this._timeout)}};_e.ActivityMonitor=Te});var it=F(tt=>{\"use strict\";Object.defineProperty(tt,\"__esModule\",{value:!0})});var nt=F(ue=>{\"use strict\";Object.defineProperty(ue,\"__esModule\",{value:!0});ue.MarkdownCodeBlocks=void 0;var pi;(function(n){n.CODE_BLOCK_MARKER=\"```\";let e=[\".markdown\",\".mdown\",\".mkdn\",\".md\",\".mkd\",\".mdwn\",\".mdtxt\",\".mdtext\",\".text\",\".txt\",\".Rmd\"];class t{constructor(r){this.startLine=r,this.code=\"\",this.endLine=-1}}n.MarkdownCodeBlock=t;function i(o){return e.indexOf(o)>-1}n.isMarkdown=i;function a(o){if(!o||o===\"\")return[];let r=o.split(`\n`),s=[],l=null;for(let m=0;m{\"use strict\";function di(n,e){var t=n;e.slice(0,-1).forEach(function(a){t=t[a]||{}});var i=e[e.length-1];return i in t}function at(n){return typeof n==\"number\"||/^0x[0-9a-f]+$/i.test(n)?!0:/^[-+]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(e[-+]?\\d+)?$/.test(n)}function ot(n,e){return e===\"constructor\"&&typeof n[e]==\"function\"||e===\"__proto__\"}st.exports=function(n,e){e||(e={});var t={bools:{},strings:{},unknownFn:null};typeof e.unknown==\"function\"&&(t.unknownFn=e.unknown),typeof e.boolean==\"boolean\"&&e.boolean?t.allBools=!0:[].concat(e.boolean).filter(Boolean).forEach(function(P){t.bools[P]=!0});var i={};function a(P){return i[P].some(function(N){return t.bools[N]})}Object.keys(e.alias||{}).forEach(function(P){i[P]=[].concat(e.alias[P]),i[P].forEach(function(N){i[N]=[P].concat(i[P].filter(function(V){return N!==V}))})}),[].concat(e.string).filter(Boolean).forEach(function(P){t.strings[P]=!0,i[P]&&[].concat(i[P]).forEach(function(N){t.strings[N]=!0})});var o=e.default||{},r={_:[]};function s(P,N){return t.allBools&&/^--[^=]+$/.test(N)||t.strings[P]||t.bools[P]||i[P]}function l(P,N,V){for(var D=P,z=0;z{\"use strict\";function ee(n){if(typeof n!=\"string\")throw new TypeError(\"Path must be a string. Received \"+JSON.stringify(n))}function lt(n,e){for(var t=\"\",i=0,a=-1,o=0,r,s=0;s<=n.length;++s){if(s2){var l=t.lastIndexOf(\"/\");if(l!==t.length-1){l===-1?(t=\"\",i=0):(t=t.slice(0,l),i=t.length-1-t.lastIndexOf(\"/\")),a=s,o=0;continue}}else if(t.length===2||t.length===1){t=\"\",i=0,a=s,o=0;continue}}e&&(t.length>0?t+=\"/..\":t=\"..\",i=2)}else t.length>0?t+=\"/\"+n.slice(a+1,s):t=n.slice(a+1,s),i=s-a-1;a=s,o=0}else r===46&&o!==-1?++o:o=-1}return t}function mi(n,e){var t=e.dir||e.root,i=e.base||(e.name||\"\")+(e.ext||\"\");return t?t===e.root?t+i:t+n+i:i}var de={resolve:function(){for(var e=\"\",t=!1,i,a=arguments.length-1;a>=-1&&!t;a--){var o;a>=0?o=arguments[a]:(i===void 0&&(i=process.cwd()),o=i),ee(o),o.length!==0&&(e=o+\"/\"+e,t=o.charCodeAt(0)===47)}return e=lt(e,!t),t?e.length>0?\"/\"+e:\"/\":e.length>0?e:\".\"},normalize:function(e){if(ee(e),e.length===0)return\".\";var t=e.charCodeAt(0)===47,i=e.charCodeAt(e.length-1)===47;return e=lt(e,!t),e.length===0&&!t&&(e=\".\"),e.length>0&&i&&(e+=\"/\"),t?\"/\"+e:e},isAbsolute:function(e){return ee(e),e.length>0&&e.charCodeAt(0)===47},join:function(){if(arguments.length===0)return\".\";for(var e,t=0;t0&&(e===void 0?e=i:e+=\"/\"+i)}return e===void 0?\".\":de.normalize(e)},relative:function(e,t){if(ee(e),ee(t),e===t||(e=de.resolve(e),t=de.resolve(t),e===t))return\"\";for(var i=1;im){if(t.charCodeAt(r+c)===47)return t.slice(r+c+1);if(c===0)return t.slice(r+c)}else o>m&&(e.charCodeAt(i+c)===47?h=c:c===0&&(h=0));break}var b=e.charCodeAt(i+c),j=t.charCodeAt(r+c);if(b!==j)break;b===47&&(h=c)}var C=\"\";for(c=i+h+1;c<=a;++c)(c===a||e.charCodeAt(c)===47)&&(C.length===0?C+=\"..\":C+=\"/..\");return C.length>0?C+t.slice(r+h):(r+=h,t.charCodeAt(r)===47&&++r,t.slice(r))},_makeLong:function(e){return e},dirname:function(e){if(ee(e),e.length===0)return\".\";for(var t=e.charCodeAt(0),i=t===47,a=-1,o=!0,r=e.length-1;r>=1;--r)if(t=e.charCodeAt(r),t===47){if(!o){a=r;break}}else o=!1;return a===-1?i?\"/\":\".\":i&&a===1?\"//\":e.slice(0,a)},basename:function(e,t){if(t!==void 0&&typeof t!=\"string\")throw new TypeError('\"ext\" argument must be a string');ee(e);var i=0,a=-1,o=!0,r;if(t!==void 0&&t.length>0&&t.length<=e.length){if(t.length===e.length&&t===e)return\"\";var s=t.length-1,l=-1;for(r=e.length-1;r>=0;--r){var m=e.charCodeAt(r);if(m===47){if(!o){i=r+1;break}}else l===-1&&(o=!1,l=r+1),s>=0&&(m===t.charCodeAt(s)?--s===-1&&(a=r):(s=-1,a=l))}return i===a?a=l:a===-1&&(a=e.length),e.slice(i,a)}else{for(r=e.length-1;r>=0;--r)if(e.charCodeAt(r)===47){if(!o){i=r+1;break}}else a===-1&&(o=!1,a=r+1);return a===-1?\"\":e.slice(i,a)}},extname:function(e){ee(e);for(var t=-1,i=0,a=-1,o=!0,r=0,s=e.length-1;s>=0;--s){var l=e.charCodeAt(s);if(l===47){if(!o){i=s+1;break}continue}a===-1&&(o=!1,a=s+1),l===46?t===-1?t=s:r!==1&&(r=1):t!==-1&&(r=-1)}return t===-1||a===-1||r===0||r===1&&t===a-1&&t===i+1?\"\":e.slice(t,a)},format:function(e){if(e===null||typeof e!=\"object\")throw new TypeError('The \"pathObject\" argument must be of type Object. Received type '+typeof e);return mi(\"/\",e)},parse:function(e){ee(e);var t={root:\"\",dir:\"\",base:\"\",ext:\"\",name:\"\"};if(e.length===0)return t;var i=e.charCodeAt(0),a=i===47,o;a?(t.root=\"/\",o=1):o=0;for(var r=-1,s=0,l=-1,m=!0,h=e.length-1,c=0;h>=o;--h){if(i=e.charCodeAt(h),i===47){if(!m){s=h+1;break}continue}l===-1&&(m=!1,l=h+1),i===46?r===-1?r=h:c!==1&&(c=1):r!==-1&&(c=-1)}return r===-1||l===-1||c===0||c===1&&r===l-1&&r===s+1?l!==-1&&(s===0&&a?t.base=t.name=e.slice(1,l):t.base=t.name=e.slice(s,l)):(s===0&&a?(t.name=e.slice(1,r),t.base=e.slice(1,l)):(t.name=e.slice(s,r),t.base=e.slice(s,l)),t.ext=e.slice(r,l)),s>0?t.dir=e.slice(0,s-1):a&&(t.dir=\"/\"),t},sep:\"/\",delimiter:\":\",win32:null,posix:null};de.posix=de;ct.exports=de});var dt=F((Ji,pt)=>{\"use strict\";pt.exports=function(e,t){if(t=t.split(\":\")[0],e=+e,!e)return!1;switch(t){case\"http\":case\"ws\":return e!==80;case\"https\":case\"wss\":return e!==443;case\"ftp\":return e!==21;case\"gopher\":return e!==70;case\"file\":return!1}return e!==0}});var ut=F(Ae=>{\"use strict\";var fi=Object.prototype.hasOwnProperty,ui;function mt(n){try{return decodeURIComponent(n.replace(/\\+/g,\" \"))}catch{return null}}function ft(n){try{return encodeURIComponent(n)}catch{return null}}function hi(n){for(var e=/([^=?#&]+)=?([^&]*)/g,t={},i;i=e.exec(n);){var a=mt(i[1]),o=mt(i[2]);a===null||o===null||a in t||(t[a]=o)}return t}function vi(n,e){e=e||\"\";var t=[],i,a;typeof e!=\"string\"&&(e=\"?\");for(a in n)if(fi.call(n,a)){if(i=n[a],!i&&(i===null||i===ui||isNaN(i))&&(i=\"\"),a=ft(a),i=ft(i),a===null||i===null)continue;t.push(a+\"=\"+i)}return t.length?e+t.join(\"&\"):\"\"}Ae.stringify=vi;Ae.parse=hi});var _t=F((Yi,yt)=>{\"use strict\";var vt=dt(),je=ut(),gi=/^[\\x00-\\x20\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]+/,gt=/[\\n\\r\\t]/g,xi=/^[A-Za-z][A-Za-z0-9+-.]*:\\/\\//,xt=/:\\d+$/,bi=/^([a-z][a-z0-9.+-]*:)?(\\/\\/)?([\\\\/]+)?([\\S\\s]*)/i,wi=/^[a-zA-Z]:/;function Ue(n){return(n||\"\").toString().replace(gi,\"\")}var qe=[[\"#\",\"hash\"],[\"?\",\"query\"],function(e,t){return te(t.protocol)?e.replace(/\\\\/g,\"/\"):e},[\"/\",\"pathname\"],[\"@\",\"auth\",1],[NaN,\"host\",void 0,1,1],[/:(\\d*)$/,\"port\",void 0,1],[NaN,\"hostname\",void 0,1,1]],ht={hash:1,query:1};function bt(n){var e;typeof window!=\"undefined\"?e=window:typeof global!=\"undefined\"?e=global:typeof self!=\"undefined\"?e=self:e={};var t=e.location||{};n=n||t;var i={},a=typeof n,o;if(n.protocol===\"blob:\")i=new ie(unescape(n.pathname),{});else if(a===\"string\"){i=new ie(n,{});for(o in ht)delete i[o]}else if(a===\"object\"){for(o in n)o in ht||(i[o]=n[o]);i.slashes===void 0&&(i.slashes=xi.test(n.href))}return i}function te(n){return n===\"file:\"||n===\"ftp:\"||n===\"http:\"||n===\"https:\"||n===\"ws:\"||n===\"wss:\"}function wt(n,e){n=Ue(n),n=n.replace(gt,\"\"),e=e||{};var t=bi.exec(n),i=t[1]?t[1].toLowerCase():\"\",a=!!t[2],o=!!t[3],r=0,s;return a?o?(s=t[2]+t[3]+t[4],r=t[2].length+t[3].length):(s=t[2]+t[4],r=t[2].length):o?(s=t[3]+t[4],r=t[3].length):s=t[4],i===\"file:\"?r>=2&&(s=s.slice(2)):te(i)?s=t[4]:i?a&&(s=s.slice(2)):r>=2&&te(e.protocol)&&(s=t[4]),{protocol:i,slashes:a||te(i),slashesCount:r,rest:s}}function yi(n,e){if(n===\"\")return e;for(var t=(e||\"/\").split(\"/\").slice(0,-1).concat(n.split(\"/\")),i=t.length,a=t[i-1],o=!1,r=0;i--;)t[i]===\".\"?t.splice(i,1):t[i]===\"..\"?(t.splice(i,1),r++):r&&(i===0&&(o=!0),t.splice(i,1),r--);return o&&t.unshift(\"\"),(a===\".\"||a===\"..\")&&t.push(\"\"),t.join(\"/\")}function ie(n,e,t){if(n=Ue(n),n=n.replace(gt,\"\"),!(this instanceof ie))return new ie(n,e,t);var i,a,o,r,s,l,m=qe.slice(),h=typeof e,c=this,b=0;for(h!==\"object\"&&h!==\"string\"&&(t=e,e=null),t&&typeof t!=\"function\"&&(t=je.parse),e=bt(e),a=wt(n||\"\",e),i=!a.protocol&&!a.slashes,c.slashes=a.slashes||i&&e.slashes,c.protocol=a.protocol||e.protocol||\"\",n=a.rest,(a.protocol===\"file:\"&&(a.slashesCount!==2||wi.test(n))||!a.slashes&&(a.protocol||a.slashesCount<2||!te(c.protocol)))&&(m[3]=[/(.*)/,\"pathname\"]);b{\"use strict\";var ji=re&&re.__importDefault||function(n){return n&&n.__esModule?n:{default:n}};Object.defineProperty(re,\"__esModule\",{value:!0});re.URLExt=void 0;var Ci=ke(),Ce=ji(_t()),Oi;(function(n){function e(m){if(typeof document!=\"undefined\"&&document){let h=document.createElement(\"a\");return h.href=m,h}return(0,Ce.default)(m)}n.parse=e;function t(m){return(0,Ce.default)(m).hostname}n.getHostName=t;function i(m){return m&&e(m).toString()}n.normalize=i;function a(...m){let h=(0,Ce.default)(m[0],{}),c=h.protocol===\"\"&&h.slashes;c&&(h=(0,Ce.default)(m[0],\"https:\"+m[0]));let b=`${c?\"\":h.protocol}${h.slashes?\"//\":\"\"}${h.auth}${h.auth?\"@\":\"\"}${h.host}`,j=Ci.posix.join(`${b&&h.pathname[0]!==\"/\"?\"/\":\"\"}${h.pathname}`,...m.slice(1));return`${b}${j===\".\"?\"\":j}`}n.join=a;function o(m){return a(...m.split(\"/\").map(encodeURIComponent))}n.encodeParts=o;function r(m){let h=Object.keys(m).filter(c=>c.length>0);return h.length?\"?\"+h.map(c=>{let b=encodeURIComponent(String(m[c]));return c+(b?\"=\"+b:\"\")}).join(\"&\"):\"\"}n.objectToQueryString=r;function s(m){return m.replace(/^\\?/,\"\").split(\"&\").reduce((h,c)=>{let[b,j]=c.split(\"=\");return b.length>0&&(h[b]=decodeURIComponent(j||\"\")),h},{})}n.queryStringToObject=s;function l(m){let{protocol:h}=e(m);return(!h||m.toLowerCase().indexOf(h)!==0)&&m.indexOf(\"/\")!==0}n.isLocal=l})(Oi=re.URLExt||(re.URLExt={}))});var kt=F((exports,module)=>{\"use strict\";var __importDefault=exports&&exports.__importDefault||function(n){return n&&n.__esModule?n:{default:n}};Object.defineProperty(exports,\"__esModule\",{value:!0});exports.PageConfig=void 0;var coreutils_1=pe(),minimist_1=__importDefault(rt()),url_1=Ne(),PageConfig;(function(PageConfig){function getOption(name){if(configData)return configData[name]||getBodyData(name);configData=Object.create(null);let found=!1;if(typeof document!=\"undefined\"&&document){let n=document.getElementById(\"jupyter-config-data\");n&&(configData=JSON.parse(n.textContent||\"\"),found=!0)}if(!found&&typeof process!=\"undefined\"&&process.argv)try{let cli=(0,minimist_1.default)(process.argv.slice(2)),path=ke(),fullPath=\"\";\"jupyter-config-data\"in cli?fullPath=path.resolve(cli[\"jupyter-config-data\"]):\"JUPYTER_CONFIG_DATA\"in process.env&&(fullPath=path.resolve(process.env.JUPYTER_CONFIG_DATA)),fullPath&&(configData=eval(\"require\")(fullPath))}catch(n){console.error(n)}if(!coreutils_1.JSONExt.isObject(configData))configData=Object.create(null);else for(let n in configData)typeof configData[n]!=\"string\"&&(configData[n]=JSON.stringify(configData[n]));return configData[name]||getBodyData(name)}PageConfig.getOption=getOption;function setOption(n,e){let t=getOption(n);return configData[n]=e,t}PageConfig.setOption=setOption;function getBaseUrl(){return url_1.URLExt.normalize(getOption(\"baseUrl\")||\"/\")}PageConfig.getBaseUrl=getBaseUrl;function getTreeUrl(){return url_1.URLExt.join(getBaseUrl(),getOption(\"treeUrl\"))}PageConfig.getTreeUrl=getTreeUrl;function getShareUrl(){return url_1.URLExt.normalize(getOption(\"shareUrl\")||getBaseUrl())}PageConfig.getShareUrl=getShareUrl;function getTreeShareUrl(){return url_1.URLExt.normalize(url_1.URLExt.join(getShareUrl(),getOption(\"treeUrl\")))}PageConfig.getTreeShareUrl=getTreeShareUrl;function getUrl(n){var e,t,i,a;let o=n.toShare?getShareUrl():getBaseUrl(),r=(e=n.mode)!==null&&e!==void 0?e:getOption(\"mode\"),s=(t=n.workspace)!==null&&t!==void 0?t:getOption(\"workspace\"),l=r===\"single-document\"?\"doc\":\"lab\";o=url_1.URLExt.join(o,l),s!==PageConfig.defaultWorkspace&&(o=url_1.URLExt.join(o,\"workspaces\",encodeURIComponent((i=getOption(\"workspace\"))!==null&&i!==void 0?i:PageConfig.defaultWorkspace)));let m=(a=n.treePath)!==null&&a!==void 0?a:getOption(\"treePath\");return m&&(o=url_1.URLExt.join(o,\"tree\",url_1.URLExt.encodeParts(m))),o}PageConfig.getUrl=getUrl,PageConfig.defaultWorkspace=\"default\";function getWsUrl(n){let e=getOption(\"wsUrl\");if(!e){if(n=n?url_1.URLExt.normalize(n):getBaseUrl(),n.indexOf(\"http\")!==0)return\"\";e=\"ws\"+n.slice(4)}return url_1.URLExt.normalize(e)}PageConfig.getWsUrl=getWsUrl;function getNBConvertURL({path:n,format:e,download:t}){let i=url_1.URLExt.encodeParts(n),a=url_1.URLExt.join(getBaseUrl(),\"nbconvert\",e,i);return t?a+\"?download=true\":a}PageConfig.getNBConvertURL=getNBConvertURL;function getToken(){return getOption(\"token\")||getBodyData(\"jupyterApiToken\")}PageConfig.getToken=getToken;function getNotebookVersion(){let n=getOption(\"notebookVersion\");return n===\"\"?[0,0,0]:JSON.parse(n)}PageConfig.getNotebookVersion=getNotebookVersion;let configData=null;function getBodyData(n){if(typeof document==\"undefined\"||!document.body)return\"\";let e=document.body.dataset[n];return typeof e==\"undefined\"?\"\":decodeURIComponent(e)}let Extension;(function(n){function e(a){try{let o=getOption(a);if(o)return JSON.parse(o)}catch(o){console.warn(`Unable to parse ${a}.`,o)}return[]}n.deferred=e(\"deferredExtensions\"),n.disabled=e(\"disabledExtensions\");function t(a){let o=a.indexOf(\":\"),r=\"\";return o!==-1&&(r=a.slice(0,o)),n.deferred.some(s=>s===a||r&&s===r)}n.isDeferred=t;function i(a){let o=a.indexOf(\":\"),r=\"\";return o!==-1&&(r=a.slice(0,o)),n.disabled.some(s=>s===a||r&&s===r)}n.isDisabled=i})(Extension=PageConfig.Extension||(PageConfig.Extension={}))})(PageConfig=exports.PageConfig||(exports.PageConfig={}))});var jt=F(he=>{\"use strict\";Object.defineProperty(he,\"__esModule\",{value:!0});he.PathExt=void 0;var le=ke(),Pi;(function(n){function e(...h){let c=le.posix.join(...h);return c===\".\"?\"\":m(c)}n.join=e;function t(h,c){return le.posix.basename(h,c)}n.basename=t;function i(h){let c=m(le.posix.dirname(h));return c===\".\"?\"\":c}n.dirname=i;function a(h){return le.posix.extname(h)}n.extname=a;function o(h){return h===\"\"?\"\":m(le.posix.normalize(h))}n.normalize=o;function r(...h){return m(le.posix.resolve(...h))}n.resolve=r;function s(h,c){return m(le.posix.relative(h,c))}n.relative=s;function l(h){return h.length>0&&h.indexOf(\".\")!==0&&(h=`.${h}`),h}n.normalizeExtension=l;function m(h){return h.indexOf(\"/\")===0&&(h=h.slice(1)),h}n.removeSlash=m})(Pi=he.PathExt||(he.PathExt={}))});var Ct=F(Oe=>{\"use strict\";Object.defineProperty(Oe,\"__esModule\",{value:!0});Oe.signalToPromise=void 0;var Si=pe();function zi(n,e){let t=new Si.PromiseDelegate;function i(){n.disconnect(a)}function a(o,r){i(),t.resolve([o,r])}return n.connect(a),(e!=null?e:0)>0&&setTimeout(()=>{i(),t.reject(`Signal not emitted within ${e} ms.`)},e),t.promise}Oe.signalToPromise=zi});var Ot=F(ve=>{\"use strict\";Object.defineProperty(ve,\"__esModule\",{value:!0});ve.Text=void 0;var Ri;(function(n){let e=2>1;function t(r,s){if(e)return r;let l=r;for(let m=0;m+1=55296&&h<=56319){let c=s.charCodeAt(m+1);c>=56320&&c<=57343&&(l--,m++)}}return l}n.jsIndexToCharIndex=t;function i(r,s){if(e)return r;let l=r;for(let m=0;m+1=55296&&h<=56319){let c=s.charCodeAt(m+1);c>=56320&&c<=57343&&(l++,m++)}}return l}n.charIndexToJsIndex=i;function a(r,s=!1){return r.replace(/^(\\w)|[\\s-_:]+(\\w)/g,function(l,m,h){return h?h.toUpperCase():s?m.toUpperCase():m.toLowerCase()})}n.camelCase=a;function o(r){return(r||\"\").toLowerCase().split(\" \").map(s=>s.charAt(0).toUpperCase()+s.slice(1)).join(\" \")}n.titleCase=o})(Ri=ve.Text||(ve.Text={}))});var Pt=F(ge=>{\"use strict\";Object.defineProperty(ge,\"__esModule\",{value:!0});ge.Time=void 0;var Ei=[{name:\"years\",milliseconds:365*24*60*60*1e3},{name:\"months\",milliseconds:30*24*60*60*1e3},{name:\"days\",milliseconds:24*60*60*1e3},{name:\"hours\",milliseconds:60*60*1e3},{name:\"minutes\",milliseconds:60*1e3},{name:\"seconds\",milliseconds:1e3}],Ii;(function(n){function e(i){let a=document.documentElement.lang||\"en\",o=new Intl.RelativeTimeFormat(a,{numeric:\"auto\"}),r=new Date(i).getTime()-Date.now();for(let s of Ei){let l=Math.ceil(r/s.milliseconds);if(l!==0)return o.format(l,s.name)}return o.format(0,\"seconds\")}n.formatHuman=e;function t(i){let a=document.documentElement.lang||\"en\";return new Intl.DateTimeFormat(a,{dateStyle:\"short\",timeStyle:\"short\"}).format(new Date(i))}n.format=t})(Ii=ge.Time||(ge.Time={}))});var xe=F(J=>{\"use strict\";var Di=J&&J.__createBinding||(Object.create?function(n,e,t,i){i===void 0&&(i=t);var a=Object.getOwnPropertyDescriptor(e,t);(!a||(\"get\"in a?!e.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return e[t]}}),Object.defineProperty(n,i,a)}:function(n,e,t,i){i===void 0&&(i=t),n[i]=e[t]}),ae=J&&J.__exportStar||function(n,e){for(var t in n)t!==\"default\"&&!Object.prototype.hasOwnProperty.call(e,t)&&Di(e,n,t)};Object.defineProperty(J,\"__esModule\",{value:!0});ae(et(),J);ae(it(),J);ae(nt(),J);ae(kt(),J);ae(jt(),J);ae(Ct(),J);ae(Ot(),J);ae(Pt(),J);ae(Ne(),J)});var zt=F((nn,St)=>{\"use strict\";function Pe(){this._types=Object.create(null),this._extensions=Object.create(null);for(let n=0;n{Rt.exports={\"application/andrew-inset\":[\"ez\"],\"application/applixware\":[\"aw\"],\"application/atom+xml\":[\"atom\"],\"application/atomcat+xml\":[\"atomcat\"],\"application/atomdeleted+xml\":[\"atomdeleted\"],\"application/atomsvc+xml\":[\"atomsvc\"],\"application/atsc-dwd+xml\":[\"dwd\"],\"application/atsc-held+xml\":[\"held\"],\"application/atsc-rsat+xml\":[\"rsat\"],\"application/bdoc\":[\"bdoc\"],\"application/calendar+xml\":[\"xcs\"],\"application/ccxml+xml\":[\"ccxml\"],\"application/cdfx+xml\":[\"cdfx\"],\"application/cdmi-capability\":[\"cdmia\"],\"application/cdmi-container\":[\"cdmic\"],\"application/cdmi-domain\":[\"cdmid\"],\"application/cdmi-object\":[\"cdmio\"],\"application/cdmi-queue\":[\"cdmiq\"],\"application/cu-seeme\":[\"cu\"],\"application/dash+xml\":[\"mpd\"],\"application/davmount+xml\":[\"davmount\"],\"application/docbook+xml\":[\"dbk\"],\"application/dssc+der\":[\"dssc\"],\"application/dssc+xml\":[\"xdssc\"],\"application/ecmascript\":[\"es\",\"ecma\"],\"application/emma+xml\":[\"emma\"],\"application/emotionml+xml\":[\"emotionml\"],\"application/epub+zip\":[\"epub\"],\"application/exi\":[\"exi\"],\"application/express\":[\"exp\"],\"application/fdt+xml\":[\"fdt\"],\"application/font-tdpfr\":[\"pfr\"],\"application/geo+json\":[\"geojson\"],\"application/gml+xml\":[\"gml\"],\"application/gpx+xml\":[\"gpx\"],\"application/gxf\":[\"gxf\"],\"application/gzip\":[\"gz\"],\"application/hjson\":[\"hjson\"],\"application/hyperstudio\":[\"stk\"],\"application/inkml+xml\":[\"ink\",\"inkml\"],\"application/ipfix\":[\"ipfix\"],\"application/its+xml\":[\"its\"],\"application/java-archive\":[\"jar\",\"war\",\"ear\"],\"application/java-serialized-object\":[\"ser\"],\"application/java-vm\":[\"class\"],\"application/javascript\":[\"js\",\"mjs\"],\"application/json\":[\"json\",\"map\"],\"application/json5\":[\"json5\"],\"application/jsonml+json\":[\"jsonml\"],\"application/ld+json\":[\"jsonld\"],\"application/lgr+xml\":[\"lgr\"],\"application/lost+xml\":[\"lostxml\"],\"application/mac-binhex40\":[\"hqx\"],\"application/mac-compactpro\":[\"cpt\"],\"application/mads+xml\":[\"mads\"],\"application/manifest+json\":[\"webmanifest\"],\"application/marc\":[\"mrc\"],\"application/marcxml+xml\":[\"mrcx\"],\"application/mathematica\":[\"ma\",\"nb\",\"mb\"],\"application/mathml+xml\":[\"mathml\"],\"application/mbox\":[\"mbox\"],\"application/mediaservercontrol+xml\":[\"mscml\"],\"application/metalink+xml\":[\"metalink\"],\"application/metalink4+xml\":[\"meta4\"],\"application/mets+xml\":[\"mets\"],\"application/mmt-aei+xml\":[\"maei\"],\"application/mmt-usd+xml\":[\"musd\"],\"application/mods+xml\":[\"mods\"],\"application/mp21\":[\"m21\",\"mp21\"],\"application/mp4\":[\"mp4s\",\"m4p\"],\"application/msword\":[\"doc\",\"dot\"],\"application/mxf\":[\"mxf\"],\"application/n-quads\":[\"nq\"],\"application/n-triples\":[\"nt\"],\"application/node\":[\"cjs\"],\"application/octet-stream\":[\"bin\",\"dms\",\"lrf\",\"mar\",\"so\",\"dist\",\"distz\",\"pkg\",\"bpk\",\"dump\",\"elc\",\"deploy\",\"exe\",\"dll\",\"deb\",\"dmg\",\"iso\",\"img\",\"msi\",\"msp\",\"msm\",\"buffer\"],\"application/oda\":[\"oda\"],\"application/oebps-package+xml\":[\"opf\"],\"application/ogg\":[\"ogx\"],\"application/omdoc+xml\":[\"omdoc\"],\"application/onenote\":[\"onetoc\",\"onetoc2\",\"onetmp\",\"onepkg\"],\"application/oxps\":[\"oxps\"],\"application/p2p-overlay+xml\":[\"relo\"],\"application/patch-ops-error+xml\":[\"xer\"],\"application/pdf\":[\"pdf\"],\"application/pgp-encrypted\":[\"pgp\"],\"application/pgp-signature\":[\"asc\",\"sig\"],\"application/pics-rules\":[\"prf\"],\"application/pkcs10\":[\"p10\"],\"application/pkcs7-mime\":[\"p7m\",\"p7c\"],\"application/pkcs7-signature\":[\"p7s\"],\"application/pkcs8\":[\"p8\"],\"application/pkix-attr-cert\":[\"ac\"],\"application/pkix-cert\":[\"cer\"],\"application/pkix-crl\":[\"crl\"],\"application/pkix-pkipath\":[\"pkipath\"],\"application/pkixcmp\":[\"pki\"],\"application/pls+xml\":[\"pls\"],\"application/postscript\":[\"ai\",\"eps\",\"ps\"],\"application/provenance+xml\":[\"provx\"],\"application/pskc+xml\":[\"pskcxml\"],\"application/raml+yaml\":[\"raml\"],\"application/rdf+xml\":[\"rdf\",\"owl\"],\"application/reginfo+xml\":[\"rif\"],\"application/relax-ng-compact-syntax\":[\"rnc\"],\"application/resource-lists+xml\":[\"rl\"],\"application/resource-lists-diff+xml\":[\"rld\"],\"application/rls-services+xml\":[\"rs\"],\"application/route-apd+xml\":[\"rapd\"],\"application/route-s-tsid+xml\":[\"sls\"],\"application/route-usd+xml\":[\"rusd\"],\"application/rpki-ghostbusters\":[\"gbr\"],\"application/rpki-manifest\":[\"mft\"],\"application/rpki-roa\":[\"roa\"],\"application/rsd+xml\":[\"rsd\"],\"application/rss+xml\":[\"rss\"],\"application/rtf\":[\"rtf\"],\"application/sbml+xml\":[\"sbml\"],\"application/scvp-cv-request\":[\"scq\"],\"application/scvp-cv-response\":[\"scs\"],\"application/scvp-vp-request\":[\"spq\"],\"application/scvp-vp-response\":[\"spp\"],\"application/sdp\":[\"sdp\"],\"application/senml+xml\":[\"senmlx\"],\"application/sensml+xml\":[\"sensmlx\"],\"application/set-payment-initiation\":[\"setpay\"],\"application/set-registration-initiation\":[\"setreg\"],\"application/shf+xml\":[\"shf\"],\"application/sieve\":[\"siv\",\"sieve\"],\"application/smil+xml\":[\"smi\",\"smil\"],\"application/sparql-query\":[\"rq\"],\"application/sparql-results+xml\":[\"srx\"],\"application/srgs\":[\"gram\"],\"application/srgs+xml\":[\"grxml\"],\"application/sru+xml\":[\"sru\"],\"application/ssdl+xml\":[\"ssdl\"],\"application/ssml+xml\":[\"ssml\"],\"application/swid+xml\":[\"swidtag\"],\"application/tei+xml\":[\"tei\",\"teicorpus\"],\"application/thraud+xml\":[\"tfi\"],\"application/timestamped-data\":[\"tsd\"],\"application/toml\":[\"toml\"],\"application/trig\":[\"trig\"],\"application/ttml+xml\":[\"ttml\"],\"application/ubjson\":[\"ubj\"],\"application/urc-ressheet+xml\":[\"rsheet\"],\"application/urc-targetdesc+xml\":[\"td\"],\"application/voicexml+xml\":[\"vxml\"],\"application/wasm\":[\"wasm\"],\"application/widget\":[\"wgt\"],\"application/winhlp\":[\"hlp\"],\"application/wsdl+xml\":[\"wsdl\"],\"application/wspolicy+xml\":[\"wspolicy\"],\"application/xaml+xml\":[\"xaml\"],\"application/xcap-att+xml\":[\"xav\"],\"application/xcap-caps+xml\":[\"xca\"],\"application/xcap-diff+xml\":[\"xdf\"],\"application/xcap-el+xml\":[\"xel\"],\"application/xcap-ns+xml\":[\"xns\"],\"application/xenc+xml\":[\"xenc\"],\"application/xhtml+xml\":[\"xhtml\",\"xht\"],\"application/xliff+xml\":[\"xlf\"],\"application/xml\":[\"xml\",\"xsl\",\"xsd\",\"rng\"],\"application/xml-dtd\":[\"dtd\"],\"application/xop+xml\":[\"xop\"],\"application/xproc+xml\":[\"xpl\"],\"application/xslt+xml\":[\"*xsl\",\"xslt\"],\"application/xspf+xml\":[\"xspf\"],\"application/xv+xml\":[\"mxml\",\"xhvml\",\"xvml\",\"xvm\"],\"application/yang\":[\"yang\"],\"application/yin+xml\":[\"yin\"],\"application/zip\":[\"zip\"],\"audio/3gpp\":[\"*3gpp\"],\"audio/adpcm\":[\"adp\"],\"audio/amr\":[\"amr\"],\"audio/basic\":[\"au\",\"snd\"],\"audio/midi\":[\"mid\",\"midi\",\"kar\",\"rmi\"],\"audio/mobile-xmf\":[\"mxmf\"],\"audio/mp3\":[\"*mp3\"],\"audio/mp4\":[\"m4a\",\"mp4a\"],\"audio/mpeg\":[\"mpga\",\"mp2\",\"mp2a\",\"mp3\",\"m2a\",\"m3a\"],\"audio/ogg\":[\"oga\",\"ogg\",\"spx\",\"opus\"],\"audio/s3m\":[\"s3m\"],\"audio/silk\":[\"sil\"],\"audio/wav\":[\"wav\"],\"audio/wave\":[\"*wav\"],\"audio/webm\":[\"weba\"],\"audio/xm\":[\"xm\"],\"font/collection\":[\"ttc\"],\"font/otf\":[\"otf\"],\"font/ttf\":[\"ttf\"],\"font/woff\":[\"woff\"],\"font/woff2\":[\"woff2\"],\"image/aces\":[\"exr\"],\"image/apng\":[\"apng\"],\"image/avif\":[\"avif\"],\"image/bmp\":[\"bmp\"],\"image/cgm\":[\"cgm\"],\"image/dicom-rle\":[\"drle\"],\"image/emf\":[\"emf\"],\"image/fits\":[\"fits\"],\"image/g3fax\":[\"g3\"],\"image/gif\":[\"gif\"],\"image/heic\":[\"heic\"],\"image/heic-sequence\":[\"heics\"],\"image/heif\":[\"heif\"],\"image/heif-sequence\":[\"heifs\"],\"image/hej2k\":[\"hej2\"],\"image/hsj2\":[\"hsj2\"],\"image/ief\":[\"ief\"],\"image/jls\":[\"jls\"],\"image/jp2\":[\"jp2\",\"jpg2\"],\"image/jpeg\":[\"jpeg\",\"jpg\",\"jpe\"],\"image/jph\":[\"jph\"],\"image/jphc\":[\"jhc\"],\"image/jpm\":[\"jpm\"],\"image/jpx\":[\"jpx\",\"jpf\"],\"image/jxr\":[\"jxr\"],\"image/jxra\":[\"jxra\"],\"image/jxrs\":[\"jxrs\"],\"image/jxs\":[\"jxs\"],\"image/jxsc\":[\"jxsc\"],\"image/jxsi\":[\"jxsi\"],\"image/jxss\":[\"jxss\"],\"image/ktx\":[\"ktx\"],\"image/ktx2\":[\"ktx2\"],\"image/png\":[\"png\"],\"image/sgi\":[\"sgi\"],\"image/svg+xml\":[\"svg\",\"svgz\"],\"image/t38\":[\"t38\"],\"image/tiff\":[\"tif\",\"tiff\"],\"image/tiff-fx\":[\"tfx\"],\"image/webp\":[\"webp\"],\"image/wmf\":[\"wmf\"],\"message/disposition-notification\":[\"disposition-notification\"],\"message/global\":[\"u8msg\"],\"message/global-delivery-status\":[\"u8dsn\"],\"message/global-disposition-notification\":[\"u8mdn\"],\"message/global-headers\":[\"u8hdr\"],\"message/rfc822\":[\"eml\",\"mime\"],\"model/3mf\":[\"3mf\"],\"model/gltf+json\":[\"gltf\"],\"model/gltf-binary\":[\"glb\"],\"model/iges\":[\"igs\",\"iges\"],\"model/mesh\":[\"msh\",\"mesh\",\"silo\"],\"model/mtl\":[\"mtl\"],\"model/obj\":[\"obj\"],\"model/step+xml\":[\"stpx\"],\"model/step+zip\":[\"stpz\"],\"model/step-xml+zip\":[\"stpxz\"],\"model/stl\":[\"stl\"],\"model/vrml\":[\"wrl\",\"vrml\"],\"model/x3d+binary\":[\"*x3db\",\"x3dbz\"],\"model/x3d+fastinfoset\":[\"x3db\"],\"model/x3d+vrml\":[\"*x3dv\",\"x3dvz\"],\"model/x3d+xml\":[\"x3d\",\"x3dz\"],\"model/x3d-vrml\":[\"x3dv\"],\"text/cache-manifest\":[\"appcache\",\"manifest\"],\"text/calendar\":[\"ics\",\"ifb\"],\"text/coffeescript\":[\"coffee\",\"litcoffee\"],\"text/css\":[\"css\"],\"text/csv\":[\"csv\"],\"text/html\":[\"html\",\"htm\",\"shtml\"],\"text/jade\":[\"jade\"],\"text/jsx\":[\"jsx\"],\"text/less\":[\"less\"],\"text/markdown\":[\"markdown\",\"md\"],\"text/mathml\":[\"mml\"],\"text/mdx\":[\"mdx\"],\"text/n3\":[\"n3\"],\"text/plain\":[\"txt\",\"text\",\"conf\",\"def\",\"list\",\"log\",\"in\",\"ini\"],\"text/richtext\":[\"rtx\"],\"text/rtf\":[\"*rtf\"],\"text/sgml\":[\"sgml\",\"sgm\"],\"text/shex\":[\"shex\"],\"text/slim\":[\"slim\",\"slm\"],\"text/spdx\":[\"spdx\"],\"text/stylus\":[\"stylus\",\"styl\"],\"text/tab-separated-values\":[\"tsv\"],\"text/troff\":[\"t\",\"tr\",\"roff\",\"man\",\"me\",\"ms\"],\"text/turtle\":[\"ttl\"],\"text/uri-list\":[\"uri\",\"uris\",\"urls\"],\"text/vcard\":[\"vcard\"],\"text/vtt\":[\"vtt\"],\"text/xml\":[\"*xml\"],\"text/yaml\":[\"yaml\",\"yml\"],\"video/3gpp\":[\"3gp\",\"3gpp\"],\"video/3gpp2\":[\"3g2\"],\"video/h261\":[\"h261\"],\"video/h263\":[\"h263\"],\"video/h264\":[\"h264\"],\"video/iso.segment\":[\"m4s\"],\"video/jpeg\":[\"jpgv\"],\"video/jpm\":[\"*jpm\",\"jpgm\"],\"video/mj2\":[\"mj2\",\"mjp2\"],\"video/mp2t\":[\"ts\"],\"video/mp4\":[\"mp4\",\"mp4v\",\"mpg4\"],\"video/mpeg\":[\"mpeg\",\"mpg\",\"mpe\",\"m1v\",\"m2v\"],\"video/ogg\":[\"ogv\"],\"video/quicktime\":[\"qt\",\"mov\"],\"video/webm\":[\"webm\"]}});var Dt=F((on,It)=>{It.exports={\"application/prs.cww\":[\"cww\"],\"application/vnd.1000minds.decision-model+xml\":[\"1km\"],\"application/vnd.3gpp.pic-bw-large\":[\"plb\"],\"application/vnd.3gpp.pic-bw-small\":[\"psb\"],\"application/vnd.3gpp.pic-bw-var\":[\"pvb\"],\"application/vnd.3gpp2.tcap\":[\"tcap\"],\"application/vnd.3m.post-it-notes\":[\"pwn\"],\"application/vnd.accpac.simply.aso\":[\"aso\"],\"application/vnd.accpac.simply.imp\":[\"imp\"],\"application/vnd.acucobol\":[\"acu\"],\"application/vnd.acucorp\":[\"atc\",\"acutc\"],\"application/vnd.adobe.air-application-installer-package+zip\":[\"air\"],\"application/vnd.adobe.formscentral.fcdt\":[\"fcdt\"],\"application/vnd.adobe.fxp\":[\"fxp\",\"fxpl\"],\"application/vnd.adobe.xdp+xml\":[\"xdp\"],\"application/vnd.adobe.xfdf\":[\"xfdf\"],\"application/vnd.ahead.space\":[\"ahead\"],\"application/vnd.airzip.filesecure.azf\":[\"azf\"],\"application/vnd.airzip.filesecure.azs\":[\"azs\"],\"application/vnd.amazon.ebook\":[\"azw\"],\"application/vnd.americandynamics.acc\":[\"acc\"],\"application/vnd.amiga.ami\":[\"ami\"],\"application/vnd.android.package-archive\":[\"apk\"],\"application/vnd.anser-web-certificate-issue-initiation\":[\"cii\"],\"application/vnd.anser-web-funds-transfer-initiation\":[\"fti\"],\"application/vnd.antix.game-component\":[\"atx\"],\"application/vnd.apple.installer+xml\":[\"mpkg\"],\"application/vnd.apple.keynote\":[\"key\"],\"application/vnd.apple.mpegurl\":[\"m3u8\"],\"application/vnd.apple.numbers\":[\"numbers\"],\"application/vnd.apple.pages\":[\"pages\"],\"application/vnd.apple.pkpass\":[\"pkpass\"],\"application/vnd.aristanetworks.swi\":[\"swi\"],\"application/vnd.astraea-software.iota\":[\"iota\"],\"application/vnd.audiograph\":[\"aep\"],\"application/vnd.balsamiq.bmml+xml\":[\"bmml\"],\"application/vnd.blueice.multipass\":[\"mpm\"],\"application/vnd.bmi\":[\"bmi\"],\"application/vnd.businessobjects\":[\"rep\"],\"application/vnd.chemdraw+xml\":[\"cdxml\"],\"application/vnd.chipnuts.karaoke-mmd\":[\"mmd\"],\"application/vnd.cinderella\":[\"cdy\"],\"application/vnd.citationstyles.style+xml\":[\"csl\"],\"application/vnd.claymore\":[\"cla\"],\"application/vnd.cloanto.rp9\":[\"rp9\"],\"application/vnd.clonk.c4group\":[\"c4g\",\"c4d\",\"c4f\",\"c4p\",\"c4u\"],\"application/vnd.cluetrust.cartomobile-config\":[\"c11amc\"],\"application/vnd.cluetrust.cartomobile-config-pkg\":[\"c11amz\"],\"application/vnd.commonspace\":[\"csp\"],\"application/vnd.contact.cmsg\":[\"cdbcmsg\"],\"application/vnd.cosmocaller\":[\"cmc\"],\"application/vnd.crick.clicker\":[\"clkx\"],\"application/vnd.crick.clicker.keyboard\":[\"clkk\"],\"application/vnd.crick.clicker.palette\":[\"clkp\"],\"application/vnd.crick.clicker.template\":[\"clkt\"],\"application/vnd.crick.clicker.wordbank\":[\"clkw\"],\"application/vnd.criticaltools.wbs+xml\":[\"wbs\"],\"application/vnd.ctc-posml\":[\"pml\"],\"application/vnd.cups-ppd\":[\"ppd\"],\"application/vnd.curl.car\":[\"car\"],\"application/vnd.curl.pcurl\":[\"pcurl\"],\"application/vnd.dart\":[\"dart\"],\"application/vnd.data-vision.rdz\":[\"rdz\"],\"application/vnd.dbf\":[\"dbf\"],\"application/vnd.dece.data\":[\"uvf\",\"uvvf\",\"uvd\",\"uvvd\"],\"application/vnd.dece.ttml+xml\":[\"uvt\",\"uvvt\"],\"application/vnd.dece.unspecified\":[\"uvx\",\"uvvx\"],\"application/vnd.dece.zip\":[\"uvz\",\"uvvz\"],\"application/vnd.denovo.fcselayout-link\":[\"fe_launch\"],\"application/vnd.dna\":[\"dna\"],\"application/vnd.dolby.mlp\":[\"mlp\"],\"application/vnd.dpgraph\":[\"dpg\"],\"application/vnd.dreamfactory\":[\"dfac\"],\"application/vnd.ds-keypoint\":[\"kpxx\"],\"application/vnd.dvb.ait\":[\"ait\"],\"application/vnd.dvb.service\":[\"svc\"],\"application/vnd.dynageo\":[\"geo\"],\"application/vnd.ecowin.chart\":[\"mag\"],\"application/vnd.enliven\":[\"nml\"],\"application/vnd.epson.esf\":[\"esf\"],\"application/vnd.epson.msf\":[\"msf\"],\"application/vnd.epson.quickanime\":[\"qam\"],\"application/vnd.epson.salt\":[\"slt\"],\"application/vnd.epson.ssf\":[\"ssf\"],\"application/vnd.eszigno3+xml\":[\"es3\",\"et3\"],\"application/vnd.ezpix-album\":[\"ez2\"],\"application/vnd.ezpix-package\":[\"ez3\"],\"application/vnd.fdf\":[\"fdf\"],\"application/vnd.fdsn.mseed\":[\"mseed\"],\"application/vnd.fdsn.seed\":[\"seed\",\"dataless\"],\"application/vnd.flographit\":[\"gph\"],\"application/vnd.fluxtime.clip\":[\"ftc\"],\"application/vnd.framemaker\":[\"fm\",\"frame\",\"maker\",\"book\"],\"application/vnd.frogans.fnc\":[\"fnc\"],\"application/vnd.frogans.ltf\":[\"ltf\"],\"application/vnd.fsc.weblaunch\":[\"fsc\"],\"application/vnd.fujitsu.oasys\":[\"oas\"],\"application/vnd.fujitsu.oasys2\":[\"oa2\"],\"application/vnd.fujitsu.oasys3\":[\"oa3\"],\"application/vnd.fujitsu.oasysgp\":[\"fg5\"],\"application/vnd.fujitsu.oasysprs\":[\"bh2\"],\"application/vnd.fujixerox.ddd\":[\"ddd\"],\"application/vnd.fujixerox.docuworks\":[\"xdw\"],\"application/vnd.fujixerox.docuworks.binder\":[\"xbd\"],\"application/vnd.fuzzysheet\":[\"fzs\"],\"application/vnd.genomatix.tuxedo\":[\"txd\"],\"application/vnd.geogebra.file\":[\"ggb\"],\"application/vnd.geogebra.tool\":[\"ggt\"],\"application/vnd.geometry-explorer\":[\"gex\",\"gre\"],\"application/vnd.geonext\":[\"gxt\"],\"application/vnd.geoplan\":[\"g2w\"],\"application/vnd.geospace\":[\"g3w\"],\"application/vnd.gmx\":[\"gmx\"],\"application/vnd.google-apps.document\":[\"gdoc\"],\"application/vnd.google-apps.presentation\":[\"gslides\"],\"application/vnd.google-apps.spreadsheet\":[\"gsheet\"],\"application/vnd.google-earth.kml+xml\":[\"kml\"],\"application/vnd.google-earth.kmz\":[\"kmz\"],\"application/vnd.grafeq\":[\"gqf\",\"gqs\"],\"application/vnd.groove-account\":[\"gac\"],\"application/vnd.groove-help\":[\"ghf\"],\"application/vnd.groove-identity-message\":[\"gim\"],\"application/vnd.groove-injector\":[\"grv\"],\"application/vnd.groove-tool-message\":[\"gtm\"],\"application/vnd.groove-tool-template\":[\"tpl\"],\"application/vnd.groove-vcard\":[\"vcg\"],\"application/vnd.hal+xml\":[\"hal\"],\"application/vnd.handheld-entertainment+xml\":[\"zmm\"],\"application/vnd.hbci\":[\"hbci\"],\"application/vnd.hhe.lesson-player\":[\"les\"],\"application/vnd.hp-hpgl\":[\"hpgl\"],\"application/vnd.hp-hpid\":[\"hpid\"],\"application/vnd.hp-hps\":[\"hps\"],\"application/vnd.hp-jlyt\":[\"jlt\"],\"application/vnd.hp-pcl\":[\"pcl\"],\"application/vnd.hp-pclxl\":[\"pclxl\"],\"application/vnd.hydrostatix.sof-data\":[\"sfd-hdstx\"],\"application/vnd.ibm.minipay\":[\"mpy\"],\"application/vnd.ibm.modcap\":[\"afp\",\"listafp\",\"list3820\"],\"application/vnd.ibm.rights-management\":[\"irm\"],\"application/vnd.ibm.secure-container\":[\"sc\"],\"application/vnd.iccprofile\":[\"icc\",\"icm\"],\"application/vnd.igloader\":[\"igl\"],\"application/vnd.immervision-ivp\":[\"ivp\"],\"application/vnd.immervision-ivu\":[\"ivu\"],\"application/vnd.insors.igm\":[\"igm\"],\"application/vnd.intercon.formnet\":[\"xpw\",\"xpx\"],\"application/vnd.intergeo\":[\"i2g\"],\"application/vnd.intu.qbo\":[\"qbo\"],\"application/vnd.intu.qfx\":[\"qfx\"],\"application/vnd.ipunplugged.rcprofile\":[\"rcprofile\"],\"application/vnd.irepository.package+xml\":[\"irp\"],\"application/vnd.is-xpr\":[\"xpr\"],\"application/vnd.isac.fcs\":[\"fcs\"],\"application/vnd.jam\":[\"jam\"],\"application/vnd.jcp.javame.midlet-rms\":[\"rms\"],\"application/vnd.jisp\":[\"jisp\"],\"application/vnd.joost.joda-archive\":[\"joda\"],\"application/vnd.kahootz\":[\"ktz\",\"ktr\"],\"application/vnd.kde.karbon\":[\"karbon\"],\"application/vnd.kde.kchart\":[\"chrt\"],\"application/vnd.kde.kformula\":[\"kfo\"],\"application/vnd.kde.kivio\":[\"flw\"],\"application/vnd.kde.kontour\":[\"kon\"],\"application/vnd.kde.kpresenter\":[\"kpr\",\"kpt\"],\"application/vnd.kde.kspread\":[\"ksp\"],\"application/vnd.kde.kword\":[\"kwd\",\"kwt\"],\"application/vnd.kenameaapp\":[\"htke\"],\"application/vnd.kidspiration\":[\"kia\"],\"application/vnd.kinar\":[\"kne\",\"knp\"],\"application/vnd.koan\":[\"skp\",\"skd\",\"skt\",\"skm\"],\"application/vnd.kodak-descriptor\":[\"sse\"],\"application/vnd.las.las+xml\":[\"lasxml\"],\"application/vnd.llamagraphics.life-balance.desktop\":[\"lbd\"],\"application/vnd.llamagraphics.life-balance.exchange+xml\":[\"lbe\"],\"application/vnd.lotus-1-2-3\":[\"123\"],\"application/vnd.lotus-approach\":[\"apr\"],\"application/vnd.lotus-freelance\":[\"pre\"],\"application/vnd.lotus-notes\":[\"nsf\"],\"application/vnd.lotus-organizer\":[\"org\"],\"application/vnd.lotus-screencam\":[\"scm\"],\"application/vnd.lotus-wordpro\":[\"lwp\"],\"application/vnd.macports.portpkg\":[\"portpkg\"],\"application/vnd.mapbox-vector-tile\":[\"mvt\"],\"application/vnd.mcd\":[\"mcd\"],\"application/vnd.medcalcdata\":[\"mc1\"],\"application/vnd.mediastation.cdkey\":[\"cdkey\"],\"application/vnd.mfer\":[\"mwf\"],\"application/vnd.mfmp\":[\"mfm\"],\"application/vnd.micrografx.flo\":[\"flo\"],\"application/vnd.micrografx.igx\":[\"igx\"],\"application/vnd.mif\":[\"mif\"],\"application/vnd.mobius.daf\":[\"daf\"],\"application/vnd.mobius.dis\":[\"dis\"],\"application/vnd.mobius.mbk\":[\"mbk\"],\"application/vnd.mobius.mqy\":[\"mqy\"],\"application/vnd.mobius.msl\":[\"msl\"],\"application/vnd.mobius.plc\":[\"plc\"],\"application/vnd.mobius.txf\":[\"txf\"],\"application/vnd.mophun.application\":[\"mpn\"],\"application/vnd.mophun.certificate\":[\"mpc\"],\"application/vnd.mozilla.xul+xml\":[\"xul\"],\"application/vnd.ms-artgalry\":[\"cil\"],\"application/vnd.ms-cab-compressed\":[\"cab\"],\"application/vnd.ms-excel\":[\"xls\",\"xlm\",\"xla\",\"xlc\",\"xlt\",\"xlw\"],\"application/vnd.ms-excel.addin.macroenabled.12\":[\"xlam\"],\"application/vnd.ms-excel.sheet.binary.macroenabled.12\":[\"xlsb\"],\"application/vnd.ms-excel.sheet.macroenabled.12\":[\"xlsm\"],\"application/vnd.ms-excel.template.macroenabled.12\":[\"xltm\"],\"application/vnd.ms-fontobject\":[\"eot\"],\"application/vnd.ms-htmlhelp\":[\"chm\"],\"application/vnd.ms-ims\":[\"ims\"],\"application/vnd.ms-lrm\":[\"lrm\"],\"application/vnd.ms-officetheme\":[\"thmx\"],\"application/vnd.ms-outlook\":[\"msg\"],\"application/vnd.ms-pki.seccat\":[\"cat\"],\"application/vnd.ms-pki.stl\":[\"*stl\"],\"application/vnd.ms-powerpoint\":[\"ppt\",\"pps\",\"pot\"],\"application/vnd.ms-powerpoint.addin.macroenabled.12\":[\"ppam\"],\"application/vnd.ms-powerpoint.presentation.macroenabled.12\":[\"pptm\"],\"application/vnd.ms-powerpoint.slide.macroenabled.12\":[\"sldm\"],\"application/vnd.ms-powerpoint.slideshow.macroenabled.12\":[\"ppsm\"],\"application/vnd.ms-powerpoint.template.macroenabled.12\":[\"potm\"],\"application/vnd.ms-project\":[\"mpp\",\"mpt\"],\"application/vnd.ms-word.document.macroenabled.12\":[\"docm\"],\"application/vnd.ms-word.template.macroenabled.12\":[\"dotm\"],\"application/vnd.ms-works\":[\"wps\",\"wks\",\"wcm\",\"wdb\"],\"application/vnd.ms-wpl\":[\"wpl\"],\"application/vnd.ms-xpsdocument\":[\"xps\"],\"application/vnd.mseq\":[\"mseq\"],\"application/vnd.musician\":[\"mus\"],\"application/vnd.muvee.style\":[\"msty\"],\"application/vnd.mynfc\":[\"taglet\"],\"application/vnd.neurolanguage.nlu\":[\"nlu\"],\"application/vnd.nitf\":[\"ntf\",\"nitf\"],\"application/vnd.noblenet-directory\":[\"nnd\"],\"application/vnd.noblenet-sealer\":[\"nns\"],\"application/vnd.noblenet-web\":[\"nnw\"],\"application/vnd.nokia.n-gage.ac+xml\":[\"*ac\"],\"application/vnd.nokia.n-gage.data\":[\"ngdat\"],\"application/vnd.nokia.n-gage.symbian.install\":[\"n-gage\"],\"application/vnd.nokia.radio-preset\":[\"rpst\"],\"application/vnd.nokia.radio-presets\":[\"rpss\"],\"application/vnd.novadigm.edm\":[\"edm\"],\"application/vnd.novadigm.edx\":[\"edx\"],\"application/vnd.novadigm.ext\":[\"ext\"],\"application/vnd.oasis.opendocument.chart\":[\"odc\"],\"application/vnd.oasis.opendocument.chart-template\":[\"otc\"],\"application/vnd.oasis.opendocument.database\":[\"odb\"],\"application/vnd.oasis.opendocument.formula\":[\"odf\"],\"application/vnd.oasis.opendocument.formula-template\":[\"odft\"],\"application/vnd.oasis.opendocument.graphics\":[\"odg\"],\"application/vnd.oasis.opendocument.graphics-template\":[\"otg\"],\"application/vnd.oasis.opendocument.image\":[\"odi\"],\"application/vnd.oasis.opendocument.image-template\":[\"oti\"],\"application/vnd.oasis.opendocument.presentation\":[\"odp\"],\"application/vnd.oasis.opendocument.presentation-template\":[\"otp\"],\"application/vnd.oasis.opendocument.spreadsheet\":[\"ods\"],\"application/vnd.oasis.opendocument.spreadsheet-template\":[\"ots\"],\"application/vnd.oasis.opendocument.text\":[\"odt\"],\"application/vnd.oasis.opendocument.text-master\":[\"odm\"],\"application/vnd.oasis.opendocument.text-template\":[\"ott\"],\"application/vnd.oasis.opendocument.text-web\":[\"oth\"],\"application/vnd.olpc-sugar\":[\"xo\"],\"application/vnd.oma.dd2+xml\":[\"dd2\"],\"application/vnd.openblox.game+xml\":[\"obgx\"],\"application/vnd.openofficeorg.extension\":[\"oxt\"],\"application/vnd.openstreetmap.data+xml\":[\"osm\"],\"application/vnd.openxmlformats-officedocument.presentationml.presentation\":[\"pptx\"],\"application/vnd.openxmlformats-officedocument.presentationml.slide\":[\"sldx\"],\"application/vnd.openxmlformats-officedocument.presentationml.slideshow\":[\"ppsx\"],\"application/vnd.openxmlformats-officedocument.presentationml.template\":[\"potx\"],\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\":[\"xlsx\"],\"application/vnd.openxmlformats-officedocument.spreadsheetml.template\":[\"xltx\"],\"application/vnd.openxmlformats-officedocument.wordprocessingml.document\":[\"docx\"],\"application/vnd.openxmlformats-officedocument.wordprocessingml.template\":[\"dotx\"],\"application/vnd.osgeo.mapguide.package\":[\"mgp\"],\"application/vnd.osgi.dp\":[\"dp\"],\"application/vnd.osgi.subsystem\":[\"esa\"],\"application/vnd.palm\":[\"pdb\",\"pqa\",\"oprc\"],\"application/vnd.pawaafile\":[\"paw\"],\"application/vnd.pg.format\":[\"str\"],\"application/vnd.pg.osasli\":[\"ei6\"],\"application/vnd.picsel\":[\"efif\"],\"application/vnd.pmi.widget\":[\"wg\"],\"application/vnd.pocketlearn\":[\"plf\"],\"application/vnd.powerbuilder6\":[\"pbd\"],\"application/vnd.previewsystems.box\":[\"box\"],\"application/vnd.proteus.magazine\":[\"mgz\"],\"application/vnd.publishare-delta-tree\":[\"qps\"],\"application/vnd.pvi.ptid1\":[\"ptid\"],\"application/vnd.quark.quarkxpress\":[\"qxd\",\"qxt\",\"qwd\",\"qwt\",\"qxl\",\"qxb\"],\"application/vnd.rar\":[\"rar\"],\"application/vnd.realvnc.bed\":[\"bed\"],\"application/vnd.recordare.musicxml\":[\"mxl\"],\"application/vnd.recordare.musicxml+xml\":[\"musicxml\"],\"application/vnd.rig.cryptonote\":[\"cryptonote\"],\"application/vnd.rim.cod\":[\"cod\"],\"application/vnd.rn-realmedia\":[\"rm\"],\"application/vnd.rn-realmedia-vbr\":[\"rmvb\"],\"application/vnd.route66.link66+xml\":[\"link66\"],\"application/vnd.sailingtracker.track\":[\"st\"],\"application/vnd.seemail\":[\"see\"],\"application/vnd.sema\":[\"sema\"],\"application/vnd.semd\":[\"semd\"],\"application/vnd.semf\":[\"semf\"],\"application/vnd.shana.informed.formdata\":[\"ifm\"],\"application/vnd.shana.informed.formtemplate\":[\"itp\"],\"application/vnd.shana.informed.interchange\":[\"iif\"],\"application/vnd.shana.informed.package\":[\"ipk\"],\"application/vnd.simtech-mindmapper\":[\"twd\",\"twds\"],\"application/vnd.smaf\":[\"mmf\"],\"application/vnd.smart.teacher\":[\"teacher\"],\"application/vnd.software602.filler.form+xml\":[\"fo\"],\"application/vnd.solent.sdkm+xml\":[\"sdkm\",\"sdkd\"],\"application/vnd.spotfire.dxp\":[\"dxp\"],\"application/vnd.spotfire.sfs\":[\"sfs\"],\"application/vnd.stardivision.calc\":[\"sdc\"],\"application/vnd.stardivision.draw\":[\"sda\"],\"application/vnd.stardivision.impress\":[\"sdd\"],\"application/vnd.stardivision.math\":[\"smf\"],\"application/vnd.stardivision.writer\":[\"sdw\",\"vor\"],\"application/vnd.stardivision.writer-global\":[\"sgl\"],\"application/vnd.stepmania.package\":[\"smzip\"],\"application/vnd.stepmania.stepchart\":[\"sm\"],\"application/vnd.sun.wadl+xml\":[\"wadl\"],\"application/vnd.sun.xml.calc\":[\"sxc\"],\"application/vnd.sun.xml.calc.template\":[\"stc\"],\"application/vnd.sun.xml.draw\":[\"sxd\"],\"application/vnd.sun.xml.draw.template\":[\"std\"],\"application/vnd.sun.xml.impress\":[\"sxi\"],\"application/vnd.sun.xml.impress.template\":[\"sti\"],\"application/vnd.sun.xml.math\":[\"sxm\"],\"application/vnd.sun.xml.writer\":[\"sxw\"],\"application/vnd.sun.xml.writer.global\":[\"sxg\"],\"application/vnd.sun.xml.writer.template\":[\"stw\"],\"application/vnd.sus-calendar\":[\"sus\",\"susp\"],\"application/vnd.svd\":[\"svd\"],\"application/vnd.symbian.install\":[\"sis\",\"sisx\"],\"application/vnd.syncml+xml\":[\"xsm\"],\"application/vnd.syncml.dm+wbxml\":[\"bdm\"],\"application/vnd.syncml.dm+xml\":[\"xdm\"],\"application/vnd.syncml.dmddf+xml\":[\"ddf\"],\"application/vnd.tao.intent-module-archive\":[\"tao\"],\"application/vnd.tcpdump.pcap\":[\"pcap\",\"cap\",\"dmp\"],\"application/vnd.tmobile-livetv\":[\"tmo\"],\"application/vnd.trid.tpt\":[\"tpt\"],\"application/vnd.triscape.mxs\":[\"mxs\"],\"application/vnd.trueapp\":[\"tra\"],\"application/vnd.ufdl\":[\"ufd\",\"ufdl\"],\"application/vnd.uiq.theme\":[\"utz\"],\"application/vnd.umajin\":[\"umj\"],\"application/vnd.unity\":[\"unityweb\"],\"application/vnd.uoml+xml\":[\"uoml\"],\"application/vnd.vcx\":[\"vcx\"],\"application/vnd.visio\":[\"vsd\",\"vst\",\"vss\",\"vsw\"],\"application/vnd.visionary\":[\"vis\"],\"application/vnd.vsf\":[\"vsf\"],\"application/vnd.wap.wbxml\":[\"wbxml\"],\"application/vnd.wap.wmlc\":[\"wmlc\"],\"application/vnd.wap.wmlscriptc\":[\"wmlsc\"],\"application/vnd.webturbo\":[\"wtb\"],\"application/vnd.wolfram.player\":[\"nbp\"],\"application/vnd.wordperfect\":[\"wpd\"],\"application/vnd.wqd\":[\"wqd\"],\"application/vnd.wt.stf\":[\"stf\"],\"application/vnd.xara\":[\"xar\"],\"application/vnd.xfdl\":[\"xfdl\"],\"application/vnd.yamaha.hv-dic\":[\"hvd\"],\"application/vnd.yamaha.hv-script\":[\"hvs\"],\"application/vnd.yamaha.hv-voice\":[\"hvp\"],\"application/vnd.yamaha.openscoreformat\":[\"osf\"],\"application/vnd.yamaha.openscoreformat.osfpvg+xml\":[\"osfpvg\"],\"application/vnd.yamaha.smaf-audio\":[\"saf\"],\"application/vnd.yamaha.smaf-phrase\":[\"spf\"],\"application/vnd.yellowriver-custom-menu\":[\"cmp\"],\"application/vnd.zul\":[\"zir\",\"zirz\"],\"application/vnd.zzazz.deck+xml\":[\"zaz\"],\"application/x-7z-compressed\":[\"7z\"],\"application/x-abiword\":[\"abw\"],\"application/x-ace-compressed\":[\"ace\"],\"application/x-apple-diskimage\":[\"*dmg\"],\"application/x-arj\":[\"arj\"],\"application/x-authorware-bin\":[\"aab\",\"x32\",\"u32\",\"vox\"],\"application/x-authorware-map\":[\"aam\"],\"application/x-authorware-seg\":[\"aas\"],\"application/x-bcpio\":[\"bcpio\"],\"application/x-bdoc\":[\"*bdoc\"],\"application/x-bittorrent\":[\"torrent\"],\"application/x-blorb\":[\"blb\",\"blorb\"],\"application/x-bzip\":[\"bz\"],\"application/x-bzip2\":[\"bz2\",\"boz\"],\"application/x-cbr\":[\"cbr\",\"cba\",\"cbt\",\"cbz\",\"cb7\"],\"application/x-cdlink\":[\"vcd\"],\"application/x-cfs-compressed\":[\"cfs\"],\"application/x-chat\":[\"chat\"],\"application/x-chess-pgn\":[\"pgn\"],\"application/x-chrome-extension\":[\"crx\"],\"application/x-cocoa\":[\"cco\"],\"application/x-conference\":[\"nsc\"],\"application/x-cpio\":[\"cpio\"],\"application/x-csh\":[\"csh\"],\"application/x-debian-package\":[\"*deb\",\"udeb\"],\"application/x-dgc-compressed\":[\"dgc\"],\"application/x-director\":[\"dir\",\"dcr\",\"dxr\",\"cst\",\"cct\",\"cxt\",\"w3d\",\"fgd\",\"swa\"],\"application/x-doom\":[\"wad\"],\"application/x-dtbncx+xml\":[\"ncx\"],\"application/x-dtbook+xml\":[\"dtb\"],\"application/x-dtbresource+xml\":[\"res\"],\"application/x-dvi\":[\"dvi\"],\"application/x-envoy\":[\"evy\"],\"application/x-eva\":[\"eva\"],\"application/x-font-bdf\":[\"bdf\"],\"application/x-font-ghostscript\":[\"gsf\"],\"application/x-font-linux-psf\":[\"psf\"],\"application/x-font-pcf\":[\"pcf\"],\"application/x-font-snf\":[\"snf\"],\"application/x-font-type1\":[\"pfa\",\"pfb\",\"pfm\",\"afm\"],\"application/x-freearc\":[\"arc\"],\"application/x-futuresplash\":[\"spl\"],\"application/x-gca-compressed\":[\"gca\"],\"application/x-glulx\":[\"ulx\"],\"application/x-gnumeric\":[\"gnumeric\"],\"application/x-gramps-xml\":[\"gramps\"],\"application/x-gtar\":[\"gtar\"],\"application/x-hdf\":[\"hdf\"],\"application/x-httpd-php\":[\"php\"],\"application/x-install-instructions\":[\"install\"],\"application/x-iso9660-image\":[\"*iso\"],\"application/x-iwork-keynote-sffkey\":[\"*key\"],\"application/x-iwork-numbers-sffnumbers\":[\"*numbers\"],\"application/x-iwork-pages-sffpages\":[\"*pages\"],\"application/x-java-archive-diff\":[\"jardiff\"],\"application/x-java-jnlp-file\":[\"jnlp\"],\"application/x-keepass2\":[\"kdbx\"],\"application/x-latex\":[\"latex\"],\"application/x-lua-bytecode\":[\"luac\"],\"application/x-lzh-compressed\":[\"lzh\",\"lha\"],\"application/x-makeself\":[\"run\"],\"application/x-mie\":[\"mie\"],\"application/x-mobipocket-ebook\":[\"prc\",\"mobi\"],\"application/x-ms-application\":[\"application\"],\"application/x-ms-shortcut\":[\"lnk\"],\"application/x-ms-wmd\":[\"wmd\"],\"application/x-ms-wmz\":[\"wmz\"],\"application/x-ms-xbap\":[\"xbap\"],\"application/x-msaccess\":[\"mdb\"],\"application/x-msbinder\":[\"obd\"],\"application/x-mscardfile\":[\"crd\"],\"application/x-msclip\":[\"clp\"],\"application/x-msdos-program\":[\"*exe\"],\"application/x-msdownload\":[\"*exe\",\"*dll\",\"com\",\"bat\",\"*msi\"],\"application/x-msmediaview\":[\"mvb\",\"m13\",\"m14\"],\"application/x-msmetafile\":[\"*wmf\",\"*wmz\",\"*emf\",\"emz\"],\"application/x-msmoney\":[\"mny\"],\"application/x-mspublisher\":[\"pub\"],\"application/x-msschedule\":[\"scd\"],\"application/x-msterminal\":[\"trm\"],\"application/x-mswrite\":[\"wri\"],\"application/x-netcdf\":[\"nc\",\"cdf\"],\"application/x-ns-proxy-autoconfig\":[\"pac\"],\"application/x-nzb\":[\"nzb\"],\"application/x-perl\":[\"pl\",\"pm\"],\"application/x-pilot\":[\"*prc\",\"*pdb\"],\"application/x-pkcs12\":[\"p12\",\"pfx\"],\"application/x-pkcs7-certificates\":[\"p7b\",\"spc\"],\"application/x-pkcs7-certreqresp\":[\"p7r\"],\"application/x-rar-compressed\":[\"*rar\"],\"application/x-redhat-package-manager\":[\"rpm\"],\"application/x-research-info-systems\":[\"ris\"],\"application/x-sea\":[\"sea\"],\"application/x-sh\":[\"sh\"],\"application/x-shar\":[\"shar\"],\"application/x-shockwave-flash\":[\"swf\"],\"application/x-silverlight-app\":[\"xap\"],\"application/x-sql\":[\"sql\"],\"application/x-stuffit\":[\"sit\"],\"application/x-stuffitx\":[\"sitx\"],\"application/x-subrip\":[\"srt\"],\"application/x-sv4cpio\":[\"sv4cpio\"],\"application/x-sv4crc\":[\"sv4crc\"],\"application/x-t3vm-image\":[\"t3\"],\"application/x-tads\":[\"gam\"],\"application/x-tar\":[\"tar\"],\"application/x-tcl\":[\"tcl\",\"tk\"],\"application/x-tex\":[\"tex\"],\"application/x-tex-tfm\":[\"tfm\"],\"application/x-texinfo\":[\"texinfo\",\"texi\"],\"application/x-tgif\":[\"*obj\"],\"application/x-ustar\":[\"ustar\"],\"application/x-virtualbox-hdd\":[\"hdd\"],\"application/x-virtualbox-ova\":[\"ova\"],\"application/x-virtualbox-ovf\":[\"ovf\"],\"application/x-virtualbox-vbox\":[\"vbox\"],\"application/x-virtualbox-vbox-extpack\":[\"vbox-extpack\"],\"application/x-virtualbox-vdi\":[\"vdi\"],\"application/x-virtualbox-vhd\":[\"vhd\"],\"application/x-virtualbox-vmdk\":[\"vmdk\"],\"application/x-wais-source\":[\"src\"],\"application/x-web-app-manifest+json\":[\"webapp\"],\"application/x-x509-ca-cert\":[\"der\",\"crt\",\"pem\"],\"application/x-xfig\":[\"fig\"],\"application/x-xliff+xml\":[\"*xlf\"],\"application/x-xpinstall\":[\"xpi\"],\"application/x-xz\":[\"xz\"],\"application/x-zmachine\":[\"z1\",\"z2\",\"z3\",\"z4\",\"z5\",\"z6\",\"z7\",\"z8\"],\"audio/vnd.dece.audio\":[\"uva\",\"uvva\"],\"audio/vnd.digital-winds\":[\"eol\"],\"audio/vnd.dra\":[\"dra\"],\"audio/vnd.dts\":[\"dts\"],\"audio/vnd.dts.hd\":[\"dtshd\"],\"audio/vnd.lucent.voice\":[\"lvp\"],\"audio/vnd.ms-playready.media.pya\":[\"pya\"],\"audio/vnd.nuera.ecelp4800\":[\"ecelp4800\"],\"audio/vnd.nuera.ecelp7470\":[\"ecelp7470\"],\"audio/vnd.nuera.ecelp9600\":[\"ecelp9600\"],\"audio/vnd.rip\":[\"rip\"],\"audio/x-aac\":[\"aac\"],\"audio/x-aiff\":[\"aif\",\"aiff\",\"aifc\"],\"audio/x-caf\":[\"caf\"],\"audio/x-flac\":[\"flac\"],\"audio/x-m4a\":[\"*m4a\"],\"audio/x-matroska\":[\"mka\"],\"audio/x-mpegurl\":[\"m3u\"],\"audio/x-ms-wax\":[\"wax\"],\"audio/x-ms-wma\":[\"wma\"],\"audio/x-pn-realaudio\":[\"ram\",\"ra\"],\"audio/x-pn-realaudio-plugin\":[\"rmp\"],\"audio/x-realaudio\":[\"*ra\"],\"audio/x-wav\":[\"*wav\"],\"chemical/x-cdx\":[\"cdx\"],\"chemical/x-cif\":[\"cif\"],\"chemical/x-cmdf\":[\"cmdf\"],\"chemical/x-cml\":[\"cml\"],\"chemical/x-csml\":[\"csml\"],\"chemical/x-xyz\":[\"xyz\"],\"image/prs.btif\":[\"btif\"],\"image/prs.pti\":[\"pti\"],\"image/vnd.adobe.photoshop\":[\"psd\"],\"image/vnd.airzip.accelerator.azv\":[\"azv\"],\"image/vnd.dece.graphic\":[\"uvi\",\"uvvi\",\"uvg\",\"uvvg\"],\"image/vnd.djvu\":[\"djvu\",\"djv\"],\"image/vnd.dvb.subtitle\":[\"*sub\"],\"image/vnd.dwg\":[\"dwg\"],\"image/vnd.dxf\":[\"dxf\"],\"image/vnd.fastbidsheet\":[\"fbs\"],\"image/vnd.fpx\":[\"fpx\"],\"image/vnd.fst\":[\"fst\"],\"image/vnd.fujixerox.edmics-mmr\":[\"mmr\"],\"image/vnd.fujixerox.edmics-rlc\":[\"rlc\"],\"image/vnd.microsoft.icon\":[\"ico\"],\"image/vnd.ms-dds\":[\"dds\"],\"image/vnd.ms-modi\":[\"mdi\"],\"image/vnd.ms-photo\":[\"wdp\"],\"image/vnd.net-fpx\":[\"npx\"],\"image/vnd.pco.b16\":[\"b16\"],\"image/vnd.tencent.tap\":[\"tap\"],\"image/vnd.valve.source.texture\":[\"vtf\"],\"image/vnd.wap.wbmp\":[\"wbmp\"],\"image/vnd.xiff\":[\"xif\"],\"image/vnd.zbrush.pcx\":[\"pcx\"],\"image/x-3ds\":[\"3ds\"],\"image/x-cmu-raster\":[\"ras\"],\"image/x-cmx\":[\"cmx\"],\"image/x-freehand\":[\"fh\",\"fhc\",\"fh4\",\"fh5\",\"fh7\"],\"image/x-icon\":[\"*ico\"],\"image/x-jng\":[\"jng\"],\"image/x-mrsid-image\":[\"sid\"],\"image/x-ms-bmp\":[\"*bmp\"],\"image/x-pcx\":[\"*pcx\"],\"image/x-pict\":[\"pic\",\"pct\"],\"image/x-portable-anymap\":[\"pnm\"],\"image/x-portable-bitmap\":[\"pbm\"],\"image/x-portable-graymap\":[\"pgm\"],\"image/x-portable-pixmap\":[\"ppm\"],\"image/x-rgb\":[\"rgb\"],\"image/x-tga\":[\"tga\"],\"image/x-xbitmap\":[\"xbm\"],\"image/x-xpixmap\":[\"xpm\"],\"image/x-xwindowdump\":[\"xwd\"],\"message/vnd.wfa.wsc\":[\"wsc\"],\"model/vnd.collada+xml\":[\"dae\"],\"model/vnd.dwf\":[\"dwf\"],\"model/vnd.gdl\":[\"gdl\"],\"model/vnd.gtw\":[\"gtw\"],\"model/vnd.mts\":[\"mts\"],\"model/vnd.opengex\":[\"ogex\"],\"model/vnd.parasolid.transmit.binary\":[\"x_b\"],\"model/vnd.parasolid.transmit.text\":[\"x_t\"],\"model/vnd.sap.vds\":[\"vds\"],\"model/vnd.usdz+zip\":[\"usdz\"],\"model/vnd.valve.source.compiled-map\":[\"bsp\"],\"model/vnd.vtu\":[\"vtu\"],\"text/prs.lines.tag\":[\"dsc\"],\"text/vnd.curl\":[\"curl\"],\"text/vnd.curl.dcurl\":[\"dcurl\"],\"text/vnd.curl.mcurl\":[\"mcurl\"],\"text/vnd.curl.scurl\":[\"scurl\"],\"text/vnd.dvb.subtitle\":[\"sub\"],\"text/vnd.fly\":[\"fly\"],\"text/vnd.fmi.flexstor\":[\"flx\"],\"text/vnd.graphviz\":[\"gv\"],\"text/vnd.in3d.3dml\":[\"3dml\"],\"text/vnd.in3d.spot\":[\"spot\"],\"text/vnd.sun.j2me.app-descriptor\":[\"jad\"],\"text/vnd.wap.wml\":[\"wml\"],\"text/vnd.wap.wmlscript\":[\"wmls\"],\"text/x-asm\":[\"s\",\"asm\"],\"text/x-c\":[\"c\",\"cc\",\"cxx\",\"cpp\",\"h\",\"hh\",\"dic\"],\"text/x-component\":[\"htc\"],\"text/x-fortran\":[\"f\",\"for\",\"f77\",\"f90\"],\"text/x-handlebars-template\":[\"hbs\"],\"text/x-java-source\":[\"java\"],\"text/x-lua\":[\"lua\"],\"text/x-markdown\":[\"mkd\"],\"text/x-nfo\":[\"nfo\"],\"text/x-opml\":[\"opml\"],\"text/x-org\":[\"*org\"],\"text/x-pascal\":[\"p\",\"pas\"],\"text/x-processing\":[\"pde\"],\"text/x-sass\":[\"sass\"],\"text/x-scss\":[\"scss\"],\"text/x-setext\":[\"etx\"],\"text/x-sfv\":[\"sfv\"],\"text/x-suse-ymp\":[\"ymp\"],\"text/x-uuencode\":[\"uu\"],\"text/x-vcalendar\":[\"vcs\"],\"text/x-vcard\":[\"vcf\"],\"video/vnd.dece.hd\":[\"uvh\",\"uvvh\"],\"video/vnd.dece.mobile\":[\"uvm\",\"uvvm\"],\"video/vnd.dece.pd\":[\"uvp\",\"uvvp\"],\"video/vnd.dece.sd\":[\"uvs\",\"uvvs\"],\"video/vnd.dece.video\":[\"uvv\",\"uvvv\"],\"video/vnd.dvb.file\":[\"dvb\"],\"video/vnd.fvt\":[\"fvt\"],\"video/vnd.mpegurl\":[\"mxu\",\"m4u\"],\"video/vnd.ms-playready.media.pyv\":[\"pyv\"],\"video/vnd.uvvu.mp4\":[\"uvu\",\"uvvu\"],\"video/vnd.vivo\":[\"viv\"],\"video/x-f4v\":[\"f4v\"],\"video/x-fli\":[\"fli\"],\"video/x-flv\":[\"flv\"],\"video/x-m4v\":[\"m4v\"],\"video/x-matroska\":[\"mkv\",\"mk3d\",\"mks\"],\"video/x-mng\":[\"mng\"],\"video/x-ms-asf\":[\"asf\",\"asx\"],\"video/x-ms-vob\":[\"vob\"],\"video/x-ms-wm\":[\"wm\"],\"video/x-ms-wmv\":[\"wmv\"],\"video/x-ms-wmx\":[\"wmx\"],\"video/x-ms-wvx\":[\"wvx\"],\"video/x-msvideo\":[\"avi\"],\"video/x-sgi-movie\":[\"movie\"],\"video/x-smv\":[\"smv\"],\"x-conference/x-cooltalk\":[\"ice\"]}});var Tt=F((sn,Mt)=>{\"use strict\";var Mi=zt();Mt.exports=new Mi(Et(),Dt())});var At,qt,Le,Ti,Y,ne,Ai,Fe=ce(()=>{At=se(xe()),qt=se(Tt()),Le=se(pe()),Ti=new Le.Token(\"@jupyterlite/contents:IContents\");(function(n){n.JSON=\"application/json\",n.PLAIN_TEXT=\"text/plain\",n.OCTET_STREAM=\"octet/stream\"})(Y||(Y={}));(function(n){let e=JSON.parse(At.PageConfig.getOption(\"fileTypes\")||\"{}\");function t(a,o=null){a=a.toLowerCase();for(let r of Object.values(e))for(let s of r.extensions||[])if(s===a&&r.mimeTypes&&r.mimeTypes.length)return r.mimeTypes[0];return qt.default.getType(a)||o||Y.OCTET_STREAM}n.getType=t;function i(a,o){a=a.toLowerCase();for(let r of Object.values(e))if(r.fileFormat===o){for(let s of r.extensions||[])if(s===a)return!0}return!1}n.hasFormat=i})(ne||(ne={}));Ai=new Le.Token(\"@jupyterlite/contents:IBroadcastChannelWrapper\")});var oe,X,Lt,Ut,Nt,Be,Se,Ft=ce(()=>{oe=se(xe()),X=se(xe());Fe();Lt=se(pe()),Ut=\"JupyterLite Storage\",Nt=5,Be=class{constructor(e){this.reduceBytesToString=(t,i)=>t+String.fromCharCode(i),this._serverContents=new Map,this._storageName=Ut,this._storageDrivers=null,this._localforage=e.localforage,this._storageName=e.storageName||Ut,this._storageDrivers=e.storageDrivers||null,this._ready=new Lt.PromiseDelegate}async initialize(){await this.initStorage(),this._ready.resolve(void 0)}async initStorage(){this._storage=this.createDefaultStorage(),this._counters=this.createDefaultCounters(),this._checkpoints=this.createDefaultCheckpoints()}get ready(){return this._ready.promise}get storage(){return this.ready.then(()=>this._storage)}get counters(){return this.ready.then(()=>this._counters)}get checkpoints(){return this.ready.then(()=>this._checkpoints)}get defaultStorageOptions(){let e=this._storageDrivers&&this._storageDrivers.length?this._storageDrivers:null;return{version:1,name:this._storageName,...e?{driver:e}:{}}}createDefaultStorage(){return this._localforage.createInstance({description:\"Offline Storage for Notebooks and Files\",storeName:\"files\",...this.defaultStorageOptions})}createDefaultCounters(){return this._localforage.createInstance({description:\"Store the current file suffix counters\",storeName:\"counters\",...this.defaultStorageOptions})}createDefaultCheckpoints(){return this._localforage.createInstance({description:\"Offline Storage for Checkpoints\",storeName:\"checkpoints\",...this.defaultStorageOptions})}async newUntitled(e){var t,i,a;let o=(t=e==null?void 0:e.path)!==null&&t!==void 0?t:\"\",r=(i=e==null?void 0:e.type)!==null&&i!==void 0?i:\"notebook\",s=new Date().toISOString(),l=X.PathExt.dirname(o),m=X.PathExt.basename(o),h=X.PathExt.extname(o),c=await this.get(l),b=\"\";o&&!h&&c?(l=`${o}/`,b=\"\"):l&&m?(l=`${l}/`,b=m):(l=\"\",b=o);let j;switch(r){case\"directory\":{b=`Untitled Folder${await this._incrementCounter(\"directory\")||\"\"}`,j={name:b,path:`${l}${b}`,last_modified:s,created:s,format:\"json\",mimetype:\"\",content:null,size:0,writable:!0,type:\"directory\"};break}case\"notebook\":{let q=await this._incrementCounter(\"notebook\");b=b||`Untitled${q||\"\"}.ipynb`,j={name:b,path:`${l}${b}`,last_modified:s,created:s,format:\"json\",mimetype:Y.JSON,content:Se.EMPTY_NB,size:JSON.stringify(Se.EMPTY_NB).length,writable:!0,type:\"notebook\"};break}default:{let q=(a=e==null?void 0:e.ext)!==null&&a!==void 0?a:\".txt\",O=await this._incrementCounter(\"file\"),S=ne.getType(q)||Y.OCTET_STREAM,R;ne.hasFormat(q,\"text\")||S.indexOf(\"text\")!==-1?R=\"text\":q.indexOf(\"json\")!==-1||q.indexOf(\"ipynb\")!==-1?R=\"json\":R=\"base64\",b=b||`untitled${O||\"\"}${q}`,j={name:b,path:`${l}${b}`,last_modified:s,created:s,format:R,mimetype:S,content:\"\",size:0,writable:!0,type:\"file\"};break}}let C=j.path;return await(await this.storage).setItem(C,j),j}async copy(e,t){let i=X.PathExt.basename(e);for(t=t===\"\"?\"\":`${t.slice(1)}/`;await this.get(`${t}${i}`,{content:!0});){let r=X.PathExt.extname(i);i=`${i.replace(r,\"\")} (copy)${r}`}let a=`${t}${i}`,o=await this.get(e,{content:!0});if(!o)throw Error(`Could not find file with path ${e}`);return o={...o,name:i,path:a},await(await this.storage).setItem(a,o),o}async get(e,t){if(e=decodeURIComponent(e.replace(/^\\//,\"\")),e===\"\")return await this._getFolder(e);let i=await this.storage,a=await i.getItem(e),o=await this._getServerContents(e,t),r=a||o;if(!r)return null;if(!(t!=null&&t.content))return{size:0,...r,content:null};if(r.type===\"directory\"){let s=new Map;await i.iterate((h,c)=>{c===`${e}/${h.name}`&&s.set(h.name,h)});let l=o?o.content:Array.from((await this._getServerDirectory(e)).values());for(let h of l)s.has(h.name)||s.set(h.name,h);let m=[...s.values()];return{name:X.PathExt.basename(e),path:e,last_modified:r.last_modified,created:r.created,format:\"json\",mimetype:Y.JSON,content:m,size:0,writable:!0,type:\"directory\"}}return r}async rename(e,t){let i=decodeURIComponent(e),a=await this.get(i,{content:!0});if(!a)throw Error(`Could not find file with path ${i}`);let o=new Date().toISOString(),r=X.PathExt.basename(t),s={...a,name:r,path:t,last_modified:o},l=await this.storage;if(await l.setItem(t,s),await l.removeItem(i),await(await this.checkpoints).removeItem(i),a.type===\"directory\"){let m;for(m of a.content)await this.rename(oe.URLExt.join(e,m.name),oe.URLExt.join(t,m.name))}return s}async save(e,t={}){var i;e=decodeURIComponent(e);let a=X.PathExt.extname((i=t.name)!==null&&i!==void 0?i:\"\"),o=t.chunk,r=o?o>1||o===-1:!1,s=await this.get(e,{content:r});if(s||(s=await this.newUntitled({path:e,ext:a,type:\"file\"})),!s)return null;let l=s.content,m=new Date().toISOString();if(s={...s,...t,last_modified:m},t.content&&t.format===\"base64\"){let h=o?o===-1:!0;if(a===\".ipynb\"){let c=this._handleChunk(t.content,l,r);s={...s,content:h?JSON.parse(c):c,format:\"json\",type:\"notebook\",size:c.length}}else if(ne.hasFormat(a,\"json\")){let c=this._handleChunk(t.content,l,r);s={...s,content:h?JSON.parse(c):c,format:\"json\",type:\"file\",size:c.length}}else if(ne.hasFormat(a,\"text\")){let c=this._handleChunk(t.content,l,r);s={...s,content:c,format:\"text\",type:\"file\",size:c.length}}else{let c=t.content;s={...s,content:c,size:atob(c).length}}}return await(await this.storage).setItem(e,s),s}async delete(e){e=decodeURIComponent(e);let t=`${e}/`,i=(await(await this.storage).keys()).filter(a=>a===e||a.startsWith(t));await Promise.all(i.map(this.forgetPath,this))}async forgetPath(e){await Promise.all([(await this.storage).removeItem(e),(await this.checkpoints).removeItem(e)])}async createCheckpoint(e){var t;let i=await this.checkpoints;e=decodeURIComponent(e);let a=await this.get(e,{content:!0});if(!a)throw Error(`Could not find file with path ${e}`);let o=((t=await i.getItem(e))!==null&&t!==void 0?t:[]).filter(Boolean);return o.push(a),o.length>Nt&&o.splice(0,o.length-Nt),await i.setItem(e,o),{id:`${o.length-1}`,last_modified:a.last_modified}}async listCheckpoints(e){return(await(await this.checkpoints).getItem(e)||[]).filter(Boolean).map(this.normalizeCheckpoint,this)}normalizeCheckpoint(e,t){return{id:t.toString(),last_modified:e.last_modified}}async restoreCheckpoint(e,t){e=decodeURIComponent(e);let i=await(await this.checkpoints).getItem(e)||[],a=parseInt(t),o=i[a];await(await this.storage).setItem(e,o)}async deleteCheckpoint(e,t){e=decodeURIComponent(e);let i=await(await this.checkpoints).getItem(e)||[],a=parseInt(t);i.splice(a,1),await(await this.checkpoints).setItem(e,i)}_handleChunk(e,t,i){let a=decodeURIComponent(escape(atob(e)));return i?t+a:a}async _getFolder(e){let t=new Map;await(await this.storage).iterate((a,o)=>{o.includes(\"/\")||t.set(a.path,a)});for(let a of(await this._getServerDirectory(e)).values())t.has(a.path)||t.set(a.path,a);return e&&t.size===0?null:{name:\"\",path:e,last_modified:new Date(0).toISOString(),created:new Date(0).toISOString(),format:\"json\",mimetype:Y.JSON,content:Array.from(t.values()),size:0,writable:!0,type:\"directory\"}}async _getServerContents(e,t){let i=X.PathExt.basename(e),o=(await this._getServerDirectory(oe.URLExt.join(e,\"..\"))).get(i);if(!o)return null;if(o=o||{name:i,path:e,last_modified:new Date(0).toISOString(),created:new Date(0).toISOString(),format:\"text\",mimetype:Y.PLAIN_TEXT,type:\"file\",writable:!0,size:0,content:\"\"},t!=null&&t.content)if(o.type===\"directory\"){let r=await this._getServerDirectory(e);o={...o,content:Array.from(r.values())}}else{let r=oe.URLExt.join(oe.PageConfig.getBaseUrl(),\"files\",e),s=await fetch(r);if(!s.ok)return null;let l=o.mimetype||s.headers.get(\"Content-Type\"),m=X.PathExt.extname(i);if(o.type===\"notebook\"||ne.hasFormat(m,\"json\")||(l==null?void 0:l.indexOf(\"json\"))!==-1||e.match(/\\.(ipynb|[^/]*json[^/]*)$/)){let h=await s.text();o={...o,content:JSON.parse(h),format:\"json\",mimetype:o.mimetype||Y.JSON,size:h.length}}else if(ne.hasFormat(m,\"text\")||l.indexOf(\"text\")!==-1){let h=await s.text();o={...o,content:h,format:\"text\",mimetype:l||Y.PLAIN_TEXT,size:h.length}}else{let h=await s.arrayBuffer(),c=new Uint8Array(h);o={...o,content:btoa(c.reduce(this.reduceBytesToString,\"\")),format:\"base64\",mimetype:l||Y.OCTET_STREAM,size:c.length}}}return o}async _getServerDirectory(e){let t=this._serverContents.get(e)||new Map;if(!this._serverContents.has(e)){let i=oe.URLExt.join(oe.PageConfig.getBaseUrl(),\"api/contents\",e,\"all.json\");try{let a=await fetch(i),o=JSON.parse(await a.text());for(let r of o.content)t.set(r.name,r)}catch(a){console.warn(`don't worry, about ${a}... nothing's broken. If there had been a\n file at ${i}, you might see some more files.`)}this._serverContents.set(e,t)}return t}async _incrementCounter(e){var t;let i=await this.counters,o=((t=await i.getItem(e))!==null&&t!==void 0?t:-1)+1;return await i.setItem(e,o),o}};(function(n){n.EMPTY_NB={metadata:{orig_nbformat:4},nbformat_minor:4,nbformat:4,cells:[]}})(Se||(Se={}))});var ze,Bt,qi,Ui,$t=ce(()=>{ze=16895,Bt=33206,qi=1,Ui=2});var Wt,He,De,Ni,Li,Ht,Re,Ee,Ie,$e,We=ce(()=>{Wt=\":\",He=\"/api/drive.v1\",De=4096,Ni=new TextEncoder,Li=new TextDecoder(\"utf-8\"),Ht={0:!1,1:!0,2:!0,64:!0,65:!0,66:!0,129:!0,193:!0,514:!0,577:!0,578:!0,705:!0,706:!0,1024:!0,1025:!0,1026:!0,1089:!0,1090:!0,1153:!0,1154:!0,1217:!0,1218:!0,4096:!0,4098:!0},Re=class{constructor(e){this.fs=e}open(e){let t=this.fs.realPath(e.node);this.fs.FS.isFile(e.node.mode)&&(e.file=this.fs.API.get(t))}close(e){if(!this.fs.FS.isFile(e.node.mode)||!e.file)return;let t=this.fs.realPath(e.node),i=e.flags,a=typeof i==\"string\"?parseInt(i,10):i;a&=8191;let o=!0;a in Ht&&(o=Ht[a]),o&&this.fs.API.put(t,e.file),e.file=void 0}read(e,t,i,a,o){if(a<=0||e.file===void 0||o>=(e.file.data.length||0))return 0;let r=Math.min(e.file.data.length-o,a);return t.set(e.file.data.subarray(o,o+r),i),r}write(e,t,i,a,o){var r;if(a<=0||e.file===void 0)return 0;if(e.node.timestamp=Date.now(),o+a>(((r=e.file)===null||r===void 0?void 0:r.data.length)||0)){let s=e.file.data?e.file.data:new Uint8Array;e.file.data=new Uint8Array(o+a),e.file.data.set(s)}return e.file.data.set(t.subarray(i,i+a),o),a}llseek(e,t,i){let a=t;if(i===1)a+=e.position;else if(i===2&&this.fs.FS.isFile(e.node.mode))if(e.file!==void 0)a+=e.file.data.length;else throw new this.fs.FS.ErrnoError(this.fs.ERRNO_CODES.EPERM);if(a<0)throw new this.fs.FS.ErrnoError(this.fs.ERRNO_CODES.EINVAL);return a}},Ee=class{constructor(e){this.fs=e}getattr(e){return{...this.fs.API.getattr(this.fs.realPath(e)),mode:e.mode,ino:e.id}}setattr(e,t){for(let[i,a]of Object.entries(t))switch(i){case\"mode\":e.mode=a;break;case\"timestamp\":e.timestamp=a;break;default:console.warn(\"setattr\",i,\"of\",a,\"on\",e,\"not yet implemented\");break}}lookup(e,t){let i=this.fs.PATH.join2(this.fs.realPath(e),t),a=this.fs.API.lookup(i);if(!a.ok)throw this.fs.FS.genericErrors[this.fs.ERRNO_CODES.ENOENT];return this.fs.createNode(e,t,a.mode,0)}mknod(e,t,i,a){let o=this.fs.PATH.join2(this.fs.realPath(e),t);return this.fs.API.mknod(o,i),this.fs.createNode(e,t,i,a)}rename(e,t,i){this.fs.API.rename(e.parent?this.fs.PATH.join2(this.fs.realPath(e.parent),e.name):e.name,this.fs.PATH.join2(this.fs.realPath(t),i)),e.name=i,e.parent=t}unlink(e,t){this.fs.API.rmdir(this.fs.PATH.join2(this.fs.realPath(e),t))}rmdir(e,t){this.fs.API.rmdir(this.fs.PATH.join2(this.fs.realPath(e),t))}readdir(e){return this.fs.API.readdir(this.fs.realPath(e))}symlink(e,t,i){throw new this.fs.FS.ErrnoError(this.fs.ERRNO_CODES.EPERM)}readlink(e){throw new this.fs.FS.ErrnoError(this.fs.ERRNO_CODES.EPERM)}},Ie=class{constructor(e,t,i,a,o){this._baseUrl=e,this._driveName=t,this._mountpoint=i,this.FS=a,this.ERRNO_CODES=o}request(e){let t=new XMLHttpRequest;t.open(\"POST\",encodeURI(this.endpoint),!1);try{t.send(JSON.stringify(e))}catch(i){console.error(i)}if(t.status>=400)throw new this.FS.ErrnoError(this.ERRNO_CODES.EINVAL);return JSON.parse(t.responseText)}lookup(e){return this.request({method:\"lookup\",path:this.normalizePath(e)})}getmode(e){return Number.parseInt(this.request({method:\"getmode\",path:this.normalizePath(e)}))}mknod(e,t){return this.request({method:\"mknod\",path:this.normalizePath(e),data:{mode:t}})}rename(e,t){return this.request({method:\"rename\",path:this.normalizePath(e),data:{newPath:this.normalizePath(t)}})}readdir(e){let t=this.request({method:\"readdir\",path:this.normalizePath(e)});return t.push(\".\"),t.push(\"..\"),t}rmdir(e){return this.request({method:\"rmdir\",path:this.normalizePath(e)})}get(e){let t=this.request({method:\"get\",path:this.normalizePath(e)}),i=t.content,a=t.format;switch(a){case\"json\":case\"text\":return{data:Ni.encode(i),format:a};case\"base64\":{let o=atob(i),r=o.length,s=new Uint8Array(r);for(let l=0;l{Ke=se(xe());We();Je=class{constructor(e){this.isDisposed=!1,this._onMessage=async t=>{if(!this._channel)return;let{_contents:i}=this,a=t.data,o=a==null?void 0:a.path;if((a==null?void 0:a.receiver)!==\"broadcast.ts\")return;let s=null,l;switch(a==null?void 0:a.method){case\"readdir\":l=await i.get(o,{content:!0}),s=[],l.type===\"directory\"&&l.content&&(s=l.content.map(m=>m.name));break;case\"rmdir\":await i.delete(o);break;case\"rename\":await i.rename(o,a.data.newPath);break;case\"getmode\":l=await i.get(o),l.type===\"directory\"?s=16895:s=33206;break;case\"lookup\":try{l=await i.get(o),s={ok:!0,mode:l.type===\"directory\"?16895:33206}}catch{s={ok:!1}}break;case\"mknod\":l=await i.newUntitled({path:Ke.PathExt.dirname(o),type:Number.parseInt(a.data.mode)===16895?\"directory\":\"file\",ext:Ke.PathExt.extname(o)}),await i.rename(l.path,o);break;case\"getattr\":{l=await i.get(o);let m=new Date(0).toISOString();s={dev:1,nlink:1,uid:0,gid:0,rdev:0,size:l.size||0,blksize:De,blocks:Math.ceil(l.size||0/De),atime:l.last_modified||m,mtime:l.last_modified||m,ctime:l.created||m,timestamp:0};break}case\"get\":if(l=await i.get(o,{content:!0}),l.type===\"directory\")break;s={content:l.format===\"json\"?JSON.stringify(l.content):l.content,format:l.format};break;case\"put\":await i.save(o,{content:a.data.format===\"json\"?JSON.parse(a.data.data):a.data.data,type:\"file\",format:a.data.format});break;default:s=null;break}this._channel.postMessage(s)},this._channel=null,this._enabled=!1,this._contents=e.contents}get enabled(){return this._enabled}enable(){if(this._channel){console.warn(\"BroadcastChannel already created and enabled\");return}this._channel=new BroadcastChannel(He),this._channel.addEventListener(\"message\",this._onMessage),this._enabled=!0}disable(){this._channel&&(this._channel.removeEventListener(\"message\",this._onMessage),this._channel=null),this._enabled=!1}dispose(){this.isDisposed||(this.disable(),this.isDisposed=!0)}}});var Jt={};li(Jt,{BLOCK_SIZE:()=>De,BroadcastChannelWrapper:()=>Je,Contents:()=>Be,ContentsAPI:()=>Ie,DIR_MODE:()=>ze,DRIVE_API_PATH:()=>He,DRIVE_SEPARATOR:()=>Wt,DriveFS:()=>$e,DriveFSEmscriptenNodeOps:()=>Ee,DriveFSEmscriptenStreamOps:()=>Re,FILE:()=>ne,FILE_MODE:()=>Bt,IBroadcastChannelWrapper:()=>Ai,IContents:()=>Ti,MIME:()=>Y,SEEK_CUR:()=>qi,SEEK_END:()=>Ui});var Vt=ce(()=>{Ft();We();Fe();Kt();$t()});var Yt=class{constructor(){this._options=null;this._initializer=null;this._pyodide=null;this._localPath=\"\";this._driveName=\"\";this._driveFS=null;this._initialized=new Promise((e,t)=>{this._initializer={resolve:e,reject:t}})}async initialize(e){var t;if(this._options=e,e.location.includes(\":\")){let i=e.location.split(\":\");this._driveName=i[0],this._localPath=i[1]}else this._driveName=\"\",this._localPath=e.location;await this.initRuntime(e),await this.initFilesystem(e),await this.initPackageManager(e),await this.initKernel(e),await this.initGlobals(e),(t=this._initializer)==null||t.resolve()}async initRuntime(e){let{pyodideUrl:t,indexUrl:i}=e,a;t.endsWith(\".mjs\")?a=(await import(t)).loadPyodide:(importScripts(t),a=self.loadPyodide),this._pyodide=await a({indexURL:i})}async initPackageManager(e){if(!this._options)throw new Error(\"Uninitialized\");let{pipliteWheelUrl:t,disablePyPIFallback:i,pipliteUrls:a}=this._options;await this._pyodide.loadPackage([\"micropip\"]),await this._pyodide.runPythonAsync(`\n import micropip\n await micropip.install('${t}', keep_going=True)\n import piplite.piplite\n piplite.piplite._PIPLITE_DISABLE_PYPI = ${i?\"True\":\"False\"}\n piplite.piplite._PIPLITE_URLS = ${JSON.stringify(a)}\n `)}async initKernel(e){await this._pyodide.runPythonAsync(`\n await piplite.install(['sqlite3'], keep_going=True);\n await piplite.install(['ipykernel'], keep_going=True);\n await piplite.install(['comm'], keep_going=True);\n await piplite.install(['pyodide_kernel'], keep_going=True);\n await piplite.install(['ipython'], keep_going=True);\n import pyodide_kernel\n `),e.mountDrive&&this._localPath&&await this._pyodide.runPythonAsync(`\n import os;\n os.chdir(\"${this._localPath}\");\n `)}async initGlobals(e){let{globals:t}=this._pyodide;this._kernel=t.get(\"pyodide_kernel\").kernel_instance.copy(),this._stdout_stream=t.get(\"pyodide_kernel\").stdout_stream.copy(),this._stderr_stream=t.get(\"pyodide_kernel\").stderr_stream.copy(),this._interpreter=this._kernel.interpreter.copy(),this._interpreter.send_comm=this.sendComm.bind(this)}async initFilesystem(e){if(e.mountDrive){let t=\"/drive\",{FS:i,PATH:a,ERRNO_CODES:o}=this._pyodide,{baseUrl:r}=e,{DriveFS:s}=await Promise.resolve().then(()=>(Vt(),Jt)),l=new s({FS:i,PATH:a,ERRNO_CODES:o,baseUrl:r,driveName:this._driveName,mountpoint:t});i.mkdir(t),i.mount(l,{},t),i.chdir(t),this._driveFS=l}}mapToObject(e){let t=e instanceof Array?[]:{};return e.forEach((i,a)=>{t[a]=i instanceof Map||i instanceof Array?this.mapToObject(i):i}),t}formatResult(e){if(!(e instanceof this._pyodide.ffi.PyProxy))return e;let t=e.toJs();return this.mapToObject(t)}async setup(e){await this._initialized,this._kernel._parent_header=this._pyodide.toPy(e)}async execute(e,t){await this.setup(t);let i=(c,b,j)=>{let C={execution_count:c,data:this.formatResult(b),metadata:this.formatResult(j)};postMessage({parentHeader:this.formatResult(this._kernel._parent_header).header,bundle:C,type:\"execute_result\"})},a=(c,b,j)=>{let C={ename:c,evalue:b,traceback:j};postMessage({parentHeader:this.formatResult(this._kernel._parent_header).header,bundle:C,type:\"execute_error\"})},o=c=>{let b={wait:this.formatResult(c)};postMessage({parentHeader:this.formatResult(this._kernel._parent_header).header,bundle:b,type:\"clear_output\"})},r=(c,b,j)=>{let C={data:this.formatResult(c),metadata:this.formatResult(b),transient:this.formatResult(j)};postMessage({parentHeader:this.formatResult(this._kernel._parent_header).header,bundle:C,type:\"display_data\"})},s=(c,b,j)=>{let C={data:this.formatResult(c),metadata:this.formatResult(b),transient:this.formatResult(j)};postMessage({parentHeader:this.formatResult(this._kernel._parent_header).header,bundle:C,type:\"update_display_data\"})},l=(c,b)=>{let j={name:this.formatResult(c),text:this.formatResult(b)};postMessage({parentHeader:this.formatResult(this._kernel._parent_header).header,bundle:j,type:\"stream\"})};this._stdout_stream.publish_stream_callback=l,this._stderr_stream.publish_stream_callback=l,this._interpreter.display_pub.clear_output_callback=o,this._interpreter.display_pub.display_data_callback=r,this._interpreter.display_pub.update_display_data_callback=s,this._interpreter.displayhook.publish_execution_result=i,this._interpreter.input=this.input.bind(this),this._interpreter.getpass=this.getpass.bind(this);let m=await this._kernel.run(e.code),h=this.formatResult(m);return h.status===\"error\"&&a(h.ename,h.evalue,h.traceback),h}async complete(e,t){await this.setup(t);let i=this._kernel.complete(e.code,e.cursor_pos);return this.formatResult(i)}async inspect(e,t){await this.setup(t);let i=this._kernel.inspect(e.code,e.cursor_pos,e.detail_level);return this.formatResult(i)}async isComplete(e,t){await this.setup(t);let i=this._kernel.is_complete(e.code);return this.formatResult(i)}async commInfo(e,t){await this.setup(t);let i=this._kernel.comm_info(e.target_name);return{comms:this.formatResult(i),status:\"ok\"}}async commOpen(e,t){await this.setup(t);let i=this._kernel.comm_manager.comm_open(this._pyodide.toPy(null),this._pyodide.toPy(null),this._pyodide.toPy(e));return this.formatResult(i)}async commMsg(e,t){await this.setup(t);let i=this._kernel.comm_manager.comm_msg(this._pyodide.toPy(null),this._pyodide.toPy(null),this._pyodide.toPy(e));return this.formatResult(i)}async commClose(e,t){await this.setup(t);let i=this._kernel.comm_manager.comm_close(this._pyodide.toPy(null),this._pyodide.toPy(null),this._pyodide.toPy(e));return this.formatResult(i)}async inputReply(e,t){await this.setup(t),this._resolveInputReply(e)}async sendInputRequest(e,t){let i={prompt:e,password:t};postMessage({type:\"input_request\",parentHeader:this.formatResult(this._kernel._parent_header).header,content:i})}async getpass(e){return e=typeof e==\"undefined\"?\"\":e,await this.sendInputRequest(e,!0),(await new Promise(a=>{this._resolveInputReply=a})).value}async input(e){return e=typeof e==\"undefined\"?\"\":e,await this.sendInputRequest(e,!1),(await new Promise(a=>{this._resolveInputReply=a})).value}async sendComm(e,t,i,a,o){postMessage({type:e,content:this.formatResult(t),metadata:this.formatResult(i),ident:this.formatResult(a),buffers:this.formatResult(o),parentHeader:this.formatResult(this._kernel._parent_header).header})}};export{Yt as PyodideRemoteKernel};\n//# sourceMappingURL=worker.js.map\n"],"names":["ni","Object","create","Me","defineProperty","ai","getOwnPropertyDescriptor","oi","getOwnPropertyNames","si","getPrototypeOf","ri","prototype","hasOwnProperty","ce","n","e","F","exports","li","t","get","enumerable","ci","i","a","call","se","__esModule","value","Ye","be","Ve","j","u","v","x","y","S","ArrayExt","g","w","d","p","_","f","length","Math","max","min","k","U","M","K","me","firstIndexOf","lastIndexOf","findFirstIndex","findLastIndex","findFirstValue","findLastValue","lowerBound","Z","fe","upperBound","shallowEqual","slice","start","stop","step","Error","floor","move","reverse","rotate","fill","insert","removeAt","removeFirstOf","removeLastOf","removeAllOf","removeFirstWhere","index","removeLastWhere","removeAllWhere","rangeLength","ceil","StringExt","T","A","H","L","Array","W","$","indexOf","findIndices","matchSumOfSquares","G","score","indices","matchSumOfDeltas","Q","highlight","push","cmp","chain","each","empty","enumerate","every","filter","find","findIndex","map","minmax","B","once","range","reduce","Symbol","iterator","next","done","TypeError","repeat","retro","some","stride","take","toArray","from","toObject","topologicSort","Set","Map","set","has","add","zip","define","globalThis","self","lumino_algorithm","pe","we","Ze","r","s","l","m","random","JSONExt","O","isArray","emptyObject","freeze","emptyArray","isPrimitive","isObject","deepEqual","h","R","I","b","P","deepCopy","c","C","q","Random","getRandomValues","window","crypto","msCrypto","UUID","uuid4","Uint8Array","toString","o","MimeData","constructor","this","_types","_values","types","hasData","getData","setData","clearData","splice","clear","PromiseDelegate","promise","Promise","_resolve","_reject","resolve","reject","Token","name","description","_tokenStructuralPropertyT","lumino_coreutils","Xe","ye","Ge","sender","connect","disconnect","emit","disconnectBetween","disconnectSender","disconnectReceiver","disconnectAll","getExceptionHandler","exceptionHandler","setExceptionHandler","super","arguments","_pending","async","asyncIterator","args","catch","z","E","signal","thisArg","slot","console","error","WeakMap","requestAnimationFrame","setImmediate","size","N","forEach","V","D","Signal","Stream","lumino_signaling","et","_e","ActivityMonitor","Qe","_timer","_timeout","_isDisposed","_activityStopped","_onSignalFired","timeout","activityStopped","isDisposed","dispose","clearTimeout","_sender","_args","setTimeout","Te","it","tt","nt","ue","MarkdownCodeBlocks","CODE_BLOCK_MARKER","startLine","code","endLine","MarkdownCodeBlock","isMarkdown","findMarkdownCodeBlocks","split","substring","rt","Wi","st","at","test","ot","bools","strings","unknownFn","unknown","boolean","allBools","concat","Boolean","keys","alias","string","default","Number","String","match","stopEarly","apply","di","ke","Ki","ct","ee","JSON","stringify","lt","charCodeAt","de","process","cwd","normalize","isAbsolute","join","relative","_makeLong","dirname","basename","extname","format","dir","root","base","ext","mi","parse","sep","delimiter","win32","posix","dt","Ji","pt","ut","Ae","fi","mt","decodeURIComponent","replace","ft","encodeURIComponent","isNaN","exec","hi","_t","Yi","yt","vt","je","gi","gt","xi","xt","bi","wi","Ue","qe","te","protocol","NaN","ht","hash","query","bt","location","ie","unescape","pathname","slashes","href","wt","toLowerCase","slashesCount","rest","charAt","unshift","yi","port","host","hostname","username","password","auth","origin","pop","extractProtocol","trimLeft","qs","Ne","re","ji","__importDefault","URLExt","Ci","Ce","document","createElement","getHostName","encodeParts","objectToQueryString","queryStringToObject","isLocal","kt","module","PageConfig","coreutils_1","minimist_1","url_1","getOption","configData","getBodyData","found","getElementById","textContent","argv","cli","path","fullPath","JUPYTER_CONFIG_DATA","eval","setOption","getBaseUrl","getTreeUrl","getShareUrl","getTreeShareUrl","getUrl","toShare","mode","workspace","defaultWorkspace","treePath","getWsUrl","getNBConvertURL","download","getToken","getNotebookVersion","Extension","body","dataset","warn","deferred","disabled","isDeferred","isDisabled","jt","he","PathExt","le","normalizeExtension","removeSlash","Ct","Oe","signalToPromise","Si","zi","Ot","ve","Text","jsIndexToCharIndex","charIndexToJsIndex","camelCase","toUpperCase","titleCase","Pt","ge","Time","Ei","milliseconds","formatHuman","documentElement","lang","Intl","RelativeTimeFormat","numeric","Date","getTime","now","DateTimeFormat","dateStyle","timeStyle","xe","J","Di","__createBinding","writable","configurable","ae","__exportStar","zt","nn","St","Pe","_extensions","bind","getType","getExtension","substr","RegExp","$1","Et","an","Rt","Dt","on","It","Tt","sn","Mt","Mi","At","qt","Le","Ti","Y","ne","Ai","Fe","PLAIN_TEXT","OCTET_STREAM","values","extensions","mimeTypes","hasFormat","fileFormat","oe","X","Lt","Ut","Nt","Be","Se","Ft","reduceBytesToString","fromCharCode","_serverContents","_storageName","_storageDrivers","_localforage","localforage","storageName","storageDrivers","_ready","initStorage","_storage","createDefaultStorage","_counters","createDefaultCounters","_checkpoints","createDefaultCheckpoints","ready","storage","then","counters","checkpoints","defaultStorageOptions","version","driver","createInstance","storeName","type","toISOString","_incrementCounter","last_modified","created","mimetype","content","EMPTY_NB","setItem","_getFolder","getItem","_getServerContents","iterate","_getServerDirectory","removeItem","rename","chunk","newUntitled","_handleChunk","atob","startsWith","all","forgetPath","id","normalizeCheckpoint","parseInt","escape","includes","fetch","ok","headers","text","arrayBuffer","btoa","metadata","orig_nbformat","nbformat_minor","nbformat","cells","ze","Bt","qi","Ui","$t","Wt","He","De","Ni","Li","Ht","Re","Ee","Ie","$e","We","TextEncoder","TextDecoder","fs","open","realPath","node","FS","isFile","file","API","close","flags","put","read","data","subarray","write","timestamp","llseek","position","ErrnoError","ERRNO_CODES","EPERM","EINVAL","getattr","ino","setattr","entries","lookup","PATH","join2","genericErrors","ENOENT","createNode","mknod","parent","unlink","rmdir","readdir","symlink","readlink","_baseUrl","_driveName","_mountpoint","request","XMLHttpRequest","encodeURI","endpoint","send","status","responseText","method","normalizePath","getmode","newPath","encode","decode","byteLength","atime","mtime","ctime","baseUrl","driveName","mountpoint","node_ops","stream_ops","mount","isDir","getMode","Ke","Je","Kt","_onMessage","_channel","_contents","receiver","delete","dev","nlink","uid","gid","rdev","blksize","blocks","save","postMessage","_enabled","contents","enabled","enable","BroadcastChannel","addEventListener","disable","removeEventListener","Jt","BLOCK_SIZE","BroadcastChannelWrapper","Contents","ContentsAPI","DIR_MODE","DRIVE_API_PATH","DRIVE_SEPARATOR","DriveFS","DriveFSEmscriptenNodeOps","DriveFSEmscriptenStreamOps","FILE","FILE_MODE","IBroadcastChannelWrapper","IContents","MIME","SEEK_CUR","SEEK_END","Vt","Yt","_options","_initializer","_pyodide","_localPath","_driveFS","_initialized","initRuntime","initFilesystem","initPackageManager","initKernel","initGlobals","pyodideUrl","indexUrl","endsWith","loadPyodide","importScripts","indexURL","pipliteWheelUrl","disablePyPIFallback","pipliteUrls","loadPackage","runPythonAsync","mountDrive","globals","_kernel","kernel_instance","copy","_stdout_stream","stdout_stream","_stderr_stream","stderr_stream","_interpreter","interpreter","send_comm","sendComm","mkdir","chdir","mapToObject","formatResult","ffi","PyProxy","toJs","_parent_header","toPy","setup","parentHeader","header","bundle","publish_stream_callback","display_pub","clear_output_callback","wait","display_data_callback","transient","update_display_data_callback","displayhook","publish_execution_result","execution_count","input","getpass","run","ename","evalue","traceback","complete","cursor_pos","inspect","detail_level","is_complete","comm_info","target_name","comms","comm_manager","comm_open","comm_msg","comm_close","_resolveInputReply","prompt","sendInputRequest","ident","buffers"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/3217.index.js b/book/_build/html/_static/3217.index.js
new file mode 100644
index 0000000..0fa3cf0
--- /dev/null
+++ b/book/_build/html/_static/3217.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[3217],{3217:(e,t,n)=>{n.r(t),n.d(t,{go:()=>s});var r,i={break:!0,case:!0,chan:!0,const:!0,continue:!0,default:!0,defer:!0,else:!0,fallthrough:!0,for:!0,func:!0,go:!0,goto:!0,if:!0,import:!0,interface:!0,map:!0,package:!0,range:!0,return:!0,select:!0,struct:!0,switch:!0,type:!0,var:!0,bool:!0,byte:!0,complex64:!0,complex128:!0,float32:!0,float64:!0,int8:!0,int16:!0,int32:!0,int64:!0,string:!0,uint8:!0,uint16:!0,uint32:!0,uint64:!0,int:!0,uint:!0,uintptr:!0,error:!0,rune:!0,any:!0,comparable:!0},a={true:!0,false:!0,iota:!0,nil:!0,append:!0,cap:!0,close:!0,complex:!0,copy:!0,delete:!0,imag:!0,len:!0,make:!0,new:!0,panic:!0,print:!0,println:!0,real:!0,recover:!0},o=/[+\-*&^%:=<>!|\/]/;function u(e,t){var n,l=e.next();if('"'==l||"'"==l||"`"==l)return t.tokenize=(n=l,function(e,t){for(var r,i=!1,a=!1;null!=(r=e.next());){if(r==n&&!i){a=!0;break}i=!i&&"`"!=n&&"\\"==r}return(a||!i&&"`"!=n)&&(t.tokenize=u),"string"}),t.tokenize(e,t);if(/[\d\.]/.test(l))return"."==l?e.match(/^[0-9]+([eE][\-+]?[0-9]+)?/):"0"==l?e.match(/^[xX][0-9a-fA-F]+/)||e.match(/^0[0-7]+/):e.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/),"number";if(/[\[\]{}\(\),;\:\.]/.test(l))return r=l,null;if("/"==l){if(e.eat("*"))return t.tokenize=c,c(e,t);if(e.eat("/"))return e.skipToEnd(),"comment"}if(o.test(l))return e.eatWhile(o),"operator";e.eatWhile(/[\w\$_\xa1-\uffff]/);var f=e.current();return i.propertyIsEnumerable(f)?("case"!=f&&"default"!=f||(r="case"),"keyword"):a.propertyIsEnumerable(f)?"atom":"variable"}function c(e,t){for(var n,r=!1;n=e.next();){if("/"==n&&r){t.tokenize=u;break}r="*"==n}return"comment"}function l(e,t,n,r,i){this.indented=e,this.column=t,this.type=n,this.align=r,this.prev=i}function f(e,t,n){return e.context=new l(e.indented,t,n,null,e.context)}const s={name:"go",startState:function(e){return{tokenize:null,context:new l(-e,0,"top",!1),indented:0,startOfLine:!0}},token:function(e,t){var n=t.context;if(e.sol()&&(null==n.align&&(n.align=!1),t.indented=e.indentation(),t.startOfLine=!0,"case"==n.type&&(n.type="}")),e.eatSpace())return null;r=null;var i=(t.tokenize||u)(e,t);return"comment"==i||(null==n.align&&(n.align=!0),"{"==r?f(t,e.column(),"}"):"["==r?f(t,e.column(),"]"):"("==r?f(t,e.column(),")"):"case"==r?n.type="case":("}"==r&&"}"==n.type||r==n.type)&&function(e){if(e.context.prev){var t=e.context.type;")"!=t&&"]"!=t&&"}"!=t||(e.indented=e.context.indented),e.context=e.context.prev}}(t),t.startOfLine=!1),i},indent:function(e,t,n){if(e.tokenize!=u&&null!=e.tokenize)return null;var r=e.context,i=t&&t.charAt(0);if("case"==r.type&&/^(?:case|default)\b/.test(t))return r.indented;var a=i==r.type;return r.align?r.column+(a?0:1):r.indented+(a?0:n.unit)},languageData:{indentOnInput:/^\s([{}]|case |default\s*:)$/,commentTokens:{line:"//",block:{open:"/*",close:"*/"}}}}}}]);
+//# sourceMappingURL=3217.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/3217.index.js.map b/book/_build/html/_static/3217.index.js.map
new file mode 100644
index 0000000..da03e85
--- /dev/null
+++ b/book/_build/html/_static/3217.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"3217.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/go.js"],"sourcesContent":["var keywords = {\n \"break\":true, \"case\":true, \"chan\":true, \"const\":true, \"continue\":true,\n \"default\":true, \"defer\":true, \"else\":true, \"fallthrough\":true, \"for\":true,\n \"func\":true, \"go\":true, \"goto\":true, \"if\":true, \"import\":true,\n \"interface\":true, \"map\":true, \"package\":true, \"range\":true, \"return\":true,\n \"select\":true, \"struct\":true, \"switch\":true, \"type\":true, \"var\":true,\n \"bool\":true, \"byte\":true, \"complex64\":true, \"complex128\":true,\n \"float32\":true, \"float64\":true, \"int8\":true, \"int16\":true, \"int32\":true,\n \"int64\":true, \"string\":true, \"uint8\":true, \"uint16\":true, \"uint32\":true,\n \"uint64\":true, \"int\":true, \"uint\":true, \"uintptr\":true, \"error\": true,\n \"rune\":true, \"any\":true, \"comparable\":true\n};\n\nvar atoms = {\n \"true\":true, \"false\":true, \"iota\":true, \"nil\":true, \"append\":true,\n \"cap\":true, \"close\":true, \"complex\":true, \"copy\":true, \"delete\":true, \"imag\":true,\n \"len\":true, \"make\":true, \"new\":true, \"panic\":true, \"print\":true,\n \"println\":true, \"real\":true, \"recover\":true\n};\n\nvar isOperatorChar = /[+\\-*&^%:=<>!|\\/]/;\n\nvar curPunc;\n\nfunction tokenBase(stream, state) {\n var ch = stream.next();\n if (ch == '\"' || ch == \"'\" || ch == \"`\") {\n state.tokenize = tokenString(ch);\n return state.tokenize(stream, state);\n }\n if (/[\\d\\.]/.test(ch)) {\n if (ch == \".\") {\n stream.match(/^[0-9]+([eE][\\-+]?[0-9]+)?/);\n } else if (ch == \"0\") {\n stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/);\n } else {\n stream.match(/^[0-9]*\\.?[0-9]*([eE][\\-+]?[0-9]+)?/);\n }\n return \"number\";\n }\n if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n curPunc = ch;\n return null;\n }\n if (ch == \"/\") {\n if (stream.eat(\"*\")) {\n state.tokenize = tokenComment;\n return tokenComment(stream, state);\n }\n if (stream.eat(\"/\")) {\n stream.skipToEnd();\n return \"comment\";\n }\n }\n if (isOperatorChar.test(ch)) {\n stream.eatWhile(isOperatorChar);\n return \"operator\";\n }\n stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n var cur = stream.current();\n if (keywords.propertyIsEnumerable(cur)) {\n if (cur == \"case\" || cur == \"default\") curPunc = \"case\";\n return \"keyword\";\n }\n if (atoms.propertyIsEnumerable(cur)) return \"atom\";\n return \"variable\";\n}\n\nfunction tokenString(quote) {\n return function(stream, state) {\n var escaped = false, next, end = false;\n while ((next = stream.next()) != null) {\n if (next == quote && !escaped) {end = true; break;}\n escaped = !escaped && quote != \"`\" && next == \"\\\\\";\n }\n if (end || !(escaped || quote == \"`\"))\n state.tokenize = tokenBase;\n return \"string\";\n };\n}\n\nfunction tokenComment(stream, state) {\n var maybeEnd = false, ch;\n while (ch = stream.next()) {\n if (ch == \"/\" && maybeEnd) {\n state.tokenize = tokenBase;\n break;\n }\n maybeEnd = (ch == \"*\");\n }\n return \"comment\";\n}\n\nfunction Context(indented, column, type, align, prev) {\n this.indented = indented;\n this.column = column;\n this.type = type;\n this.align = align;\n this.prev = prev;\n}\nfunction pushContext(state, col, type) {\n return state.context = new Context(state.indented, col, type, null, state.context);\n}\nfunction popContext(state) {\n if (!state.context.prev) return;\n var t = state.context.type;\n if (t == \")\" || t == \"]\" || t == \"}\")\n state.indented = state.context.indented;\n return state.context = state.context.prev;\n}\n\n// Interface\n\nexport const go = {\n name: \"go\",\n startState: function(indentUnit) {\n return {\n tokenize: null,\n context: new Context(-indentUnit, 0, \"top\", false),\n indented: 0,\n startOfLine: true\n };\n },\n\n token: function(stream, state) {\n var ctx = state.context;\n if (stream.sol()) {\n if (ctx.align == null) ctx.align = false;\n state.indented = stream.indentation();\n state.startOfLine = true;\n if (ctx.type == \"case\") ctx.type = \"}\";\n }\n if (stream.eatSpace()) return null;\n curPunc = null;\n var style = (state.tokenize || tokenBase)(stream, state);\n if (style == \"comment\") return style;\n if (ctx.align == null) ctx.align = true;\n\n if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n else if (curPunc == \"case\") ctx.type = \"case\";\n else if (curPunc == \"}\" && ctx.type == \"}\") popContext(state);\n else if (curPunc == ctx.type) popContext(state);\n state.startOfLine = false;\n return style;\n },\n\n indent: function(state, textAfter, cx) {\n if (state.tokenize != tokenBase && state.tokenize != null) return null;\n var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);\n if (ctx.type == \"case\" && /^(?:case|default)\\b/.test(textAfter)) return ctx.indented;\n var closing = firstChar == ctx.type;\n if (ctx.align) return ctx.column + (closing ? 0 : 1);\n else return ctx.indented + (closing ? 0 : cx.unit);\n },\n\n languageData: {\n indentOnInput: /^\\s([{}]|case |default\\s*:)$/,\n commentTokens: {line: \"//\", block: {open: \"/*\", close: \"*/\"}}\n }\n};\n\n"],"names":["curPunc","keywords","atoms","isOperatorChar","tokenBase","stream","state","quote","ch","next","tokenize","escaped","end","test","match","eat","tokenComment","skipToEnd","eatWhile","cur","current","propertyIsEnumerable","maybeEnd","Context","indented","column","type","align","prev","this","pushContext","col","context","go","name","startState","indentUnit","startOfLine","token","ctx","sol","indentation","eatSpace","style","t","popContext","indent","textAfter","cx","firstChar","charAt","closing","unit","languageData","indentOnInput","commentTokens","line","block","open","close"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/3443.index.js b/book/_build/html/_static/3443.index.js
new file mode 100644
index 0000000..b2e49d0
--- /dev/null
+++ b/book/_build/html/_static/3443.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[3443],{23443:(e,r,t)=>{function n(e){for(var r={},t=e.split(" "),n=0;nu});var a=n("Tcl safe after append array auto_execok auto_import auto_load auto_mkindex auto_mkindex_old auto_qualify auto_reset bgerror binary break catch cd close concat continue dde eof encoding error eval exec exit expr fblocked fconfigure fcopy file fileevent filename filename flush for foreach format gets glob global history http if incr info interp join lappend lindex linsert list llength load lrange lreplace lsearch lset lsort memory msgcat namespace open package parray pid pkg::create pkg_mkIndex proc puts pwd re_syntax read regex regexp registry regsub rename resource return scan seek set socket source split string subst switch tcl_endOfWord tcl_findLibrary tcl_startOfNextWord tcl_wordBreakAfter tcl_startOfPreviousWord tcl_wordBreakBefore tcltest tclvars tell time trace unknown unset update uplevel upvar variable vwait"),o=n("if elseif else and not or eq ne in ni for foreach while switch"),i=/[+\-*&%=<>!?^\/\|]/;function l(e,r,t){return r.tokenize=t,t(e,r)}function s(e,r){var t=r.beforeParams;r.beforeParams=!1;var n,u=e.next();if('"'!=u&&"'"!=u||!r.inParams){if(/[\[\]{}\(\),;\.]/.test(u))return"("==u&&t?r.inParams=!0:")"==u&&(r.inParams=!1),null;if(/\d/.test(u))return e.eatWhile(/[\w\.]/),"number";if("#"==u)return e.eat("*")?l(e,r,c):"#"==u&&e.match(/ *\[ *\[/)?l(e,r,f):(e.skipToEnd(),"comment");if('"'==u)return e.skipTo(/"/),"comment";if("$"==u)return e.eatWhile(/[$_a-z0-9A-Z\.{:]/),e.eatWhile(/}/),r.beforeParams=!0,"builtin";if(i.test(u))return e.eatWhile(i),"comment";e.eatWhile(/[\w\$_{}\xa1-\uffff]/);var m=e.current().toLowerCase();return a&&a.propertyIsEnumerable(m)?"keyword":o&&o.propertyIsEnumerable(m)?(r.beforeParams=!0,"keyword"):null}return l(e,r,(n=u,function(e,r){for(var t,a=!1,o=!1;null!=(t=e.next());){if(t==n&&!a){o=!0;break}a=!a&&"\\"==t}return o&&(r.tokenize=s),"string"}))}function c(e,r){for(var t,n=!1;t=e.next();){if("#"==t&&n){r.tokenize=s;break}n="*"==t}return"comment"}function f(e,r){for(var t,n=0;t=e.next();){if("#"==t&&2==n){r.tokenize=s;break}"]"==t?n++:" "!=t&&(n=0)}return"meta"}const u={name:"tcl",startState:function(){return{tokenize:s,beforeParams:!1,inParams:!1}},token:function(e,r){return e.eatSpace()?null:r.tokenize(e,r)},languageData:{commentTokens:{line:"#"}}}}}]);
+//# sourceMappingURL=3443.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/3443.index.js.map b/book/_build/html/_static/3443.index.js.map
new file mode 100644
index 0000000..2aca852
--- /dev/null
+++ b/book/_build/html/_static/3443.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"3443.index.js","mappings":"+FAAA,SAASA,EAAWC,GAElB,IADA,IAAIC,EAAM,CAAC,EAAGC,EAAQF,EAAIG,MAAM,KACvBC,EAAI,EAAGA,EAAIF,EAAMG,SAAUD,EAAGH,EAAIC,EAAME,KAAM,EACvD,OAAOH,CACT,C,0BACA,IAAIK,EAAWP,EAAW,+zBAatBQ,EAAYR,EAAW,kEACvBS,EAAiB,qBACrB,SAASC,EAAMC,EAAQC,EAAOC,GAE5B,OADAD,EAAME,SAAWD,EACVA,EAAEF,EAAQC,EACnB,CACA,SAASG,EAAUJ,EAAQC,GACzB,IAAII,EAAeJ,EAAMI,aACzBJ,EAAMI,cAAe,EACrB,IAwCmBC,EAxCfC,EAAKP,EAAOQ,OAChB,GAAW,KAAND,GAAmB,KAANA,IAAcN,EAAMQ,SAE/B,IAAI,mBAAmBC,KAAKH,GAGjC,MAFU,KAANA,GAAaF,EAAcJ,EAAMQ,UAAW,EACjC,KAANF,IAAWN,EAAMQ,UAAW,GAC9B,KACF,GAAI,KAAKC,KAAKH,GAEnB,OADAP,EAAOW,SAAS,UACT,SACF,GAAU,KAANJ,EACT,OAAIP,EAAOY,IAAI,KACNb,EAAMC,EAAQC,EAAOY,GACpB,KAANN,GAAaP,EAAOc,MAAM,YACrBf,EAAMC,EAAQC,EAAOc,IAC9Bf,EAAOgB,YACA,WACF,GAAU,KAANT,EAET,OADAP,EAAOiB,OAAO,KACP,UACF,GAAU,KAANV,EAIT,OAHAP,EAAOW,SAAS,qBAChBX,EAAOW,SAAS,KAChBV,EAAMI,cAAe,EACd,UACF,GAAIP,EAAeY,KAAKH,GAE7B,OADAP,EAAOW,SAASb,GACT,UAEPE,EAAOW,SAAS,wBAChB,IAAIO,EAAOlB,EAAOmB,UAAUC,cAC5B,OAAIxB,GAAYA,EAASyB,qBAAqBH,GACrC,UACLrB,GAAaA,EAAUwB,qBAAqBH,IAC9CjB,EAAMI,cAAe,EACd,WAEF,IACT,CApCE,OAAON,EAAMC,EAAQC,GAsCJK,EAtCuBC,EAuCnC,SAASP,EAAQC,GAEtB,IADA,IAAqBO,EAAjBc,GAAU,EAAaC,GAAM,EACA,OAAzBf,EAAOR,EAAOQ,SAAiB,CACrC,GAAIA,GAAQF,IAAUgB,EAAS,CAC7BC,GAAM,EACN,KACF,CACAD,GAAWA,GAAmB,MAARd,CACxB,CAEA,OADIe,IAAKtB,EAAME,SAAWC,GACnB,QACT,GAbF,CAeA,SAASS,EAAab,EAAQC,GAE5B,IADA,IAAsBM,EAAlBiB,GAAW,EACRjB,EAAKP,EAAOQ,QAAQ,CACzB,GAAU,KAAND,GAAaiB,EAAU,CACzBvB,EAAME,SAAWC,EACjB,KACF,CACAoB,EAAkB,KAANjB,CACd,CACA,MAAO,SACT,CACA,SAASQ,EAAcf,EAAQC,GAE7B,IADA,IAAkBM,EAAdiB,EAAW,EACRjB,EAAKP,EAAOQ,QAAQ,CACzB,GAAU,KAAND,GAAyB,GAAZiB,EAAe,CAC9BvB,EAAME,SAAWC,EACjB,KACF,CACU,KAANG,EACFiB,IACa,KAANjB,IACPiB,EAAW,EACf,CACA,MAAO,MACT,CACO,MAAMC,EAAM,CACjBC,KAAM,MACNC,WAAY,WACV,MAAO,CACLxB,SAAUC,EACVC,cAAc,EACdI,UAAU,EAEd,EACAmB,MAAO,SAAS5B,EAAQC,GACtB,OAAID,EAAO6B,WAAmB,KACvB5B,EAAME,SAASH,EAAQC,EAChC,EACA6B,aAAc,CACZC,cAAe,CAACC,KAAM,M","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/tcl.js"],"sourcesContent":["function parseWords(str) {\n var obj = {}, words = str.split(\" \");\n for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n return obj;\n}\nvar keywords = parseWords(\"Tcl safe after append array auto_execok auto_import auto_load \" +\n \"auto_mkindex auto_mkindex_old auto_qualify auto_reset bgerror \" +\n \"binary break catch cd close concat continue dde eof encoding error \" +\n \"eval exec exit expr fblocked fconfigure fcopy file fileevent filename \" +\n \"filename flush for foreach format gets glob global history http if \" +\n \"incr info interp join lappend lindex linsert list llength load lrange \" +\n \"lreplace lsearch lset lsort memory msgcat namespace open package parray \" +\n \"pid pkg::create pkg_mkIndex proc puts pwd re_syntax read regex regexp \" +\n \"registry regsub rename resource return scan seek set socket source split \" +\n \"string subst switch tcl_endOfWord tcl_findLibrary tcl_startOfNextWord \" +\n \"tcl_wordBreakAfter tcl_startOfPreviousWord tcl_wordBreakBefore tcltest \" +\n \"tclvars tell time trace unknown unset update uplevel upvar variable \" +\n \"vwait\");\nvar functions = parseWords(\"if elseif else and not or eq ne in ni for foreach while switch\");\nvar isOperatorChar = /[+\\-*&%=<>!?^\\/\\|]/;\nfunction chain(stream, state, f) {\n state.tokenize = f;\n return f(stream, state);\n}\nfunction tokenBase(stream, state) {\n var beforeParams = state.beforeParams;\n state.beforeParams = false;\n var ch = stream.next();\n if ((ch == '\"' || ch == \"'\") && state.inParams) {\n return chain(stream, state, tokenString(ch));\n } else if (/[\\[\\]{}\\(\\),;\\.]/.test(ch)) {\n if (ch == \"(\" && beforeParams) state.inParams = true;\n else if (ch == \")\") state.inParams = false;\n return null;\n } else if (/\\d/.test(ch)) {\n stream.eatWhile(/[\\w\\.]/);\n return \"number\";\n } else if (ch == \"#\") {\n if (stream.eat(\"*\"))\n return chain(stream, state, tokenComment);\n if (ch == \"#\" && stream.match(/ *\\[ *\\[/))\n return chain(stream, state, tokenUnparsed);\n stream.skipToEnd();\n return \"comment\";\n } else if (ch == '\"') {\n stream.skipTo(/\"/);\n return \"comment\";\n } else if (ch == \"$\") {\n stream.eatWhile(/[$_a-z0-9A-Z\\.{:]/);\n stream.eatWhile(/}/);\n state.beforeParams = true;\n return \"builtin\";\n } else if (isOperatorChar.test(ch)) {\n stream.eatWhile(isOperatorChar);\n return \"comment\";\n } else {\n stream.eatWhile(/[\\w\\$_{}\\xa1-\\uffff]/);\n var word = stream.current().toLowerCase();\n if (keywords && keywords.propertyIsEnumerable(word))\n return \"keyword\";\n if (functions && functions.propertyIsEnumerable(word)) {\n state.beforeParams = true;\n return \"keyword\";\n }\n return null;\n }\n}\nfunction tokenString(quote) {\n return function(stream, state) {\n var escaped = false, next, end = false;\n while ((next = stream.next()) != null) {\n if (next == quote && !escaped) {\n end = true;\n break;\n }\n escaped = !escaped && next == \"\\\\\";\n }\n if (end) state.tokenize = tokenBase;\n return \"string\";\n };\n}\nfunction tokenComment(stream, state) {\n var maybeEnd = false, ch;\n while (ch = stream.next()) {\n if (ch == \"#\" && maybeEnd) {\n state.tokenize = tokenBase;\n break;\n }\n maybeEnd = (ch == \"*\");\n }\n return \"comment\";\n}\nfunction tokenUnparsed(stream, state) {\n var maybeEnd = 0, ch;\n while (ch = stream.next()) {\n if (ch == \"#\" && maybeEnd == 2) {\n state.tokenize = tokenBase;\n break;\n }\n if (ch == \"]\")\n maybeEnd++;\n else if (ch != \" \")\n maybeEnd = 0;\n }\n return \"meta\";\n}\nexport const tcl = {\n name: \"tcl\",\n startState: function() {\n return {\n tokenize: tokenBase,\n beforeParams: false,\n inParams: false\n };\n },\n token: function(stream, state) {\n if (stream.eatSpace()) return null;\n return state.tokenize(stream, state);\n },\n languageData: {\n commentTokens: {line: \"#\"}\n }\n};\n"],"names":["parseWords","str","obj","words","split","i","length","keywords","functions","isOperatorChar","chain","stream","state","f","tokenize","tokenBase","beforeParams","quote","ch","next","inParams","test","eatWhile","eat","tokenComment","match","tokenUnparsed","skipToEnd","skipTo","word","current","toLowerCase","propertyIsEnumerable","escaped","end","maybeEnd","tcl","name","startState","token","eatSpace","languageData","commentTokens","line"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/3506.index.js b/book/_build/html/_static/3506.index.js
new file mode 100644
index 0000000..a24ea14
--- /dev/null
+++ b/book/_build/html/_static/3506.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[3506],{3506:(e,r,t)=>{t.r(r),t.d(r,{diff:()=>s});var n={"+":"inserted","-":"deleted","@":"meta"};const s={name:"diff",token:function(e){var r=e.string.search(/[\t ]+?$/);if(!e.sol()||0===r)return e.skipToEnd(),("error "+(n[e.string.charAt(0)]||"")).replace(/ $/,"");var t=n[e.peek()]||e.skipToEnd();return-1===r?e.skipToEnd():e.pos=r,t}}}}]);
+//# sourceMappingURL=3506.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/3506.index.js.map b/book/_build/html/_static/3506.index.js.map
new file mode 100644
index 0000000..6d4c1b6
--- /dev/null
+++ b/book/_build/html/_static/3506.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"3506.index.js","mappings":"yHAAA,IAAIA,EAAc,CAChB,IAAK,WACL,IAAK,UACL,IAAK,QAGA,MAAMC,EAAO,CAClBC,KAAM,OACNC,MAAO,SAASC,GACd,IAAIC,EAASD,EAAOE,OAAOC,OAAO,YAElC,IAAKH,EAAOI,OAAoB,IAAXH,EAEnB,OADAD,EAAOK,aACC,UACNT,EAAYI,EAAOE,OAAOI,OAAO,KAAO,KAAKC,QAAQ,KAAM,IAG/D,IAAIC,EAAaZ,EAAYI,EAAOS,SAAWT,EAAOK,YAQtD,OANgB,IAAZJ,EACFD,EAAOK,YAEPL,EAAOU,IAAMT,EAGRO,CACT,E","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/diff.js"],"sourcesContent":["var TOKEN_NAMES = {\n '+': 'inserted',\n '-': 'deleted',\n '@': 'meta'\n};\n\nexport const diff = {\n name: \"diff\",\n token: function(stream) {\n var tw_pos = stream.string.search(/[\\t ]+?$/);\n\n if (!stream.sol() || tw_pos === 0) {\n stream.skipToEnd();\n return (\"error \" + (\n TOKEN_NAMES[stream.string.charAt(0)] || '')).replace(/ $/, '');\n }\n\n var token_name = TOKEN_NAMES[stream.peek()] || stream.skipToEnd();\n\n if (tw_pos === -1) {\n stream.skipToEnd();\n } else {\n stream.pos = tw_pos;\n }\n\n return token_name;\n }\n};\n\n"],"names":["TOKEN_NAMES","diff","name","token","stream","tw_pos","string","search","sol","skipToEnd","charAt","replace","token_name","peek","pos"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/3560.index.js b/book/_build/html/_static/3560.index.js
new file mode 100644
index 0000000..22682cc
--- /dev/null
+++ b/book/_build/html/_static/3560.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[3560],{33560:(e,t,n)=>{n.r(t),n.d(t,{erlang:()=>C});var r=["-type","-spec","-export_type","-opaque"],i=["after","begin","catch","case","cond","end","fun","if","let","of","query","receive","try","when"],o=/[\->,;]/,a=["->",";",","],c=["and","andalso","band","bnot","bor","bsl","bsr","bxor","div","not","or","orelse","rem","xor"],u=/[\+\-\*\/<>=\|:!]/,s=["=","+","-","*","/",">",">=","<","=<","=:=","==","=/=","/=","||","<-","!"],l=/[<\(\[\{]/,_=["<<","(","[","{"],f=/[>\)\]\}]/,p=["}","]",")",">>"],m=["is_atom","is_binary","is_bitstring","is_boolean","is_float","is_function","is_integer","is_list","is_number","is_pid","is_port","is_record","is_reference","is_tuple","atom","binary","bitstring","boolean","function","integer","list","number","pid","port","record","reference","tuple"],b=["abs","adler32","adler32_combine","alive","apply","atom_to_binary","atom_to_list","binary_to_atom","binary_to_existing_atom","binary_to_list","binary_to_term","bit_size","bitstring_to_list","byte_size","check_process_code","contact_binary","crc32","crc32_combine","date","decode_packet","delete_module","disconnect_node","element","erase","exit","float","float_to_list","garbage_collect","get","get_keys","group_leader","halt","hd","integer_to_list","internal_bif","iolist_size","iolist_to_binary","is_alive","is_atom","is_binary","is_bitstring","is_boolean","is_float","is_function","is_integer","is_list","is_number","is_pid","is_port","is_process_alive","is_record","is_reference","is_tuple","length","link","list_to_atom","list_to_binary","list_to_bitstring","list_to_existing_atom","list_to_float","list_to_integer","list_to_pid","list_to_tuple","load_module","make_ref","module_loaded","monitor_node","node","node_link","node_unlink","nodes","notalive","now","open_port","pid_to_list","port_close","port_command","port_connect","port_control","pre_loaded","process_flag","process_info","processes","purge_module","put","register","registered","round","self","setelement","size","spawn","spawn_link","spawn_monitor","spawn_opt","split_binary","statistics","term_to_binary","time","throw","tl","trunc","tuple_size","tuple_to_list","unlink","unregister","whereis"],d=/[\w@Ø-ÞÀ-Öß-öø-ÿ]/,k=/[0-7]{1,3}|[bdefnrstv\\"']|\^[a-zA-Z]|x[0-9a-zA-Z]{2}|x{[0-9a-zA-Z]+}/;function g(e,t,n){if(1==e.current().length&&t.test(e.current())){for(e.backUp(1);t.test(e.peek());)if(e.next(),x(e.current(),n))return!0;e.backUp(e.current().length-1)}return!1}function h(e,t,n){if(1==e.current().length&&t.test(e.current())){for(;t.test(e.peek());)e.next();for(;01&&"fun"===e[t].type&&"fun"===e[t-1].token)return e.slice(0,t-1);switch(e[t].token){case"}":return A(e,{g:["{"]});case"]":return A(e,{i:["["]});case")":return A(e,{i:["("]});case">>":return A(e,{i:["<<"]});case"end":return A(e,{i:["begin","case","fun","if","receive","try"]});case",":return A(e,{e:["begin","try","when","->",",","(","[","{","<<"]});case"->":return A(e,{r:["when"],m:["try","if","case","receive"]});case";":return A(e,{E:["case","fun","if","receive","try","when"]});case"catch":return A(e,{e:["try"]});case"of":return A(e,{e:["case"]});case"after":return A(e,{e:["receive","try"]});default:return e}}(e.tokenStack))}(e,function(e,t){return z(t.current(),t.column(),t.indentation(),e)}(n,t)),n){case"atom":case"boolean":return"atom";case"attribute":return"attribute";case"builtin":return"builtin";case"close_paren":case"colon":case"dot":case"open_paren":case"separator":default:return null;case"comment":return"comment";case"error":return"error";case"fun":return"meta";case"function":return"tag";case"guard":return"property";case"keyword":return"keyword";case"macro":return"macroName";case"number":return"number";case"operator":return"operator";case"record":return"bracket";case"string":return"string";case"type":return"def";case"variable":return"variable"}}function z(e,t,n,r){return{token:e,column:t,indent:n,type:r}}function W(e){return z(e,0,0,e)}function U(e,t){var n=e.tokenStack.length,r=t||1;return!(n({tokenStack:[],in_string:!1,in_atom:!1}),token:function(e,t){if(t.in_string)return t.in_string=!y(e),S(t,e,"string");if(t.in_atom)return t.in_atom=!v(e),S(t,e,"atom");if(e.eatSpace())return S(t,e,"whitespace");if(!U(t)&&e.match(/-\s*[a-zß-öø-ÿ][\wØ-ÞÀ-Öß-öø-ÿ]*/))return x(e.current(),r)?S(t,e,"type"):S(t,e,"attribute");var n=e.next();if("%"==n)return e.skipToEnd(),S(t,e,"comment");if(":"==n)return S(t,e,"colon");if("?"==n)return e.eatSpace(),e.eatWhile(d),S(t,e,"macro");if("#"==n)return e.eatSpace(),e.eatWhile(d),S(t,e,"record");if("$"==n)return"\\"!=e.next()||e.match(k)?S(t,e,"number"):S(t,e,"error");if("."==n)return S(t,e,"dot");if("'"==n){if(!(t.in_atom=!v(e))){if(e.match(/\s*\/\s*[0-9]/,!1))return e.match(/\s*\/\s*[0-9]/,!0),S(t,e,"fun");if(e.match(/\s*\(/,!1)||e.match(/\s*:/,!1))return S(t,e,"function")}return S(t,e,"atom")}if('"'==n)return t.in_string=!y(e),S(t,e,"string");if(/[A-Z_Ø-ÞÀ-Ö]/.test(n))return e.eatWhile(d),S(t,e,"variable");if(/[a-z_ß-öø-ÿ]/.test(n)){if(e.eatWhile(d),e.match(/\s*\/\s*[0-9]/,!1))return e.match(/\s*\/\s*[0-9]/,!0),S(t,e,"fun");var w=e.current();return x(w,i)?S(t,e,"keyword"):x(w,c)?S(t,e,"operator"):e.match(/\s*\(/,!1)?!x(w,b)||":"==U(t).token&&"erlang"!=U(t,2).token?x(w,m)?S(t,e,"guard"):S(t,e,"function"):S(t,e,"builtin"):":"==function(e){var t=e.match(/^\s*([^\s%])/,!1);return t?t[1]:""}(e)?S(t,e,"erlang"==w?"builtin":"function"):x(w,["true","false"])?S(t,e,"boolean"):S(t,e,"atom")}var z=/[0-9]/;return z.test(n)?(e.eatWhile(z),e.eat("#")?e.eatWhile(/[0-9a-zA-Z]/)||e.backUp(1):e.eat(".")&&(e.eatWhile(z)?e.eat(/[eE]/)&&(e.eat(/[-+]/)?e.eatWhile(z)||e.backUp(2):e.eatWhile(z)||e.backUp(1)):e.backUp(1)),S(t,e,"number")):g(e,l,_)?S(t,e,"open_paren"):g(e,f,p)?S(t,e,"close_paren"):h(e,o,a)?S(t,e,"separator"):h(e,u,s)?S(t,e,"operator"):S(t,e,null)},indent:function(e,t,n){var r,i,o=q(i=t.match(/,|[a-z]+|\}|\]|\)|>>|\|+|\(/))&&0===i.index?i[0]:"",a=U(e,1),c=U(e,2);return e.in_string||e.in_atom?null:c?"when"==a.token?a.column+n.unit:"when"===o&&"function"===c.type?c.indent+n.unit:"("===o&&"fun"===a.token?a.column+3:"catch"===o&&(r=E(e,["try"]))?r.column:x(o,["end","after","of"])?(r=E(e,["begin","case","fun","if","receive","try"]))?r.column:null:x(o,p)?(r=E(e,_))?r.column:null:x(a.token,[",","|","||"])||x(o,[",","|","||"])?(r=function(e){var t=e.tokenStack.slice(0,-1),n=Z(t,"type",["open_paren"]);return!!q(t[n])&&t[n]}(e))?r.column+r.token.length:n.unit:"->"==a.token?x(c.token,["receive","case","if","try"])?c.column+n.unit+n.unit:c.column+n.unit:x(a.token,_)?a.column+a.token.length:(r=function(e){var t=e.tokenStack,n=Z(t,"type",["open_paren","separator","keyword"]),r=Z(t,"type",["operator"]);return q(n)&&q(r)&&n,;]/;\nvar separatorWords = [\n \"->\",\";\",\",\"];\n\nvar operatorAtomWords = [\n \"and\",\"andalso\",\"band\",\"bnot\",\"bor\",\"bsl\",\"bsr\",\"bxor\",\n \"div\",\"not\",\"or\",\"orelse\",\"rem\",\"xor\"];\n\nvar operatorSymbolRE = /[\\+\\-\\*\\/<>=\\|:!]/;\nvar operatorSymbolWords = [\n \"=\",\"+\",\"-\",\"*\",\"/\",\">\",\">=\",\"<\",\"=<\",\"=:=\",\"==\",\"=/=\",\"/=\",\"||\",\"<-\",\"!\"];\n\nvar openParenRE = /[<\\(\\[\\{]/;\nvar openParenWords = [\n \"<<\",\"(\",\"[\",\"{\"];\n\nvar closeParenRE = /[>\\)\\]\\}]/;\nvar closeParenWords = [\n \"}\",\"]\",\")\",\">>\"];\n\nvar guardWords = [\n \"is_atom\",\"is_binary\",\"is_bitstring\",\"is_boolean\",\"is_float\",\n \"is_function\",\"is_integer\",\"is_list\",\"is_number\",\"is_pid\",\n \"is_port\",\"is_record\",\"is_reference\",\"is_tuple\",\n \"atom\",\"binary\",\"bitstring\",\"boolean\",\"function\",\"integer\",\"list\",\n \"number\",\"pid\",\"port\",\"record\",\"reference\",\"tuple\"];\n\nvar bifWords = [\n \"abs\",\"adler32\",\"adler32_combine\",\"alive\",\"apply\",\"atom_to_binary\",\n \"atom_to_list\",\"binary_to_atom\",\"binary_to_existing_atom\",\n \"binary_to_list\",\"binary_to_term\",\"bit_size\",\"bitstring_to_list\",\n \"byte_size\",\"check_process_code\",\"contact_binary\",\"crc32\",\n \"crc32_combine\",\"date\",\"decode_packet\",\"delete_module\",\n \"disconnect_node\",\"element\",\"erase\",\"exit\",\"float\",\"float_to_list\",\n \"garbage_collect\",\"get\",\"get_keys\",\"group_leader\",\"halt\",\"hd\",\n \"integer_to_list\",\"internal_bif\",\"iolist_size\",\"iolist_to_binary\",\n \"is_alive\",\"is_atom\",\"is_binary\",\"is_bitstring\",\"is_boolean\",\n \"is_float\",\"is_function\",\"is_integer\",\"is_list\",\"is_number\",\"is_pid\",\n \"is_port\",\"is_process_alive\",\"is_record\",\"is_reference\",\"is_tuple\",\n \"length\",\"link\",\"list_to_atom\",\"list_to_binary\",\"list_to_bitstring\",\n \"list_to_existing_atom\",\"list_to_float\",\"list_to_integer\",\n \"list_to_pid\",\"list_to_tuple\",\"load_module\",\"make_ref\",\"module_loaded\",\n \"monitor_node\",\"node\",\"node_link\",\"node_unlink\",\"nodes\",\"notalive\",\n \"now\",\"open_port\",\"pid_to_list\",\"port_close\",\"port_command\",\n \"port_connect\",\"port_control\",\"pre_loaded\",\"process_flag\",\n \"process_info\",\"processes\",\"purge_module\",\"put\",\"register\",\n \"registered\",\"round\",\"self\",\"setelement\",\"size\",\"spawn\",\"spawn_link\",\n \"spawn_monitor\",\"spawn_opt\",\"split_binary\",\"statistics\",\n \"term_to_binary\",\"time\",\"throw\",\"tl\",\"trunc\",\"tuple_size\",\n \"tuple_to_list\",\"unlink\",\"unregister\",\"whereis\"];\n\n// upper case: [A-Z] [Ø-Þ] [À-Ö]\n// lower case: [a-z] [ß-ö] [ø-ÿ]\nvar anumRE = /[\\w@Ø-ÞÀ-Öß-öø-ÿ]/;\nvar escapesRE =\n /[0-7]{1,3}|[bdefnrstv\\\\\"']|\\^[a-zA-Z]|x[0-9a-zA-Z]{2}|x{[0-9a-zA-Z]+}/;\n\n/////////////////////////////////////////////////////////////////////////////\n// tokenizer\n\nfunction tokenizer(stream,state) {\n // in multi-line string\n if (state.in_string) {\n state.in_string = (!doubleQuote(stream));\n return rval(state,stream,\"string\");\n }\n\n // in multi-line atom\n if (state.in_atom) {\n state.in_atom = (!singleQuote(stream));\n return rval(state,stream,\"atom\");\n }\n\n // whitespace\n if (stream.eatSpace()) {\n return rval(state,stream,\"whitespace\");\n }\n\n // attributes and type specs\n if (!peekToken(state) &&\n stream.match(/-\\s*[a-zß-öø-ÿ][\\wØ-ÞÀ-Öß-öø-ÿ]*/)) {\n if (is_member(stream.current(),typeWords)) {\n return rval(state,stream,\"type\");\n }else{\n return rval(state,stream,\"attribute\");\n }\n }\n\n var ch = stream.next();\n\n // comment\n if (ch == '%') {\n stream.skipToEnd();\n return rval(state,stream,\"comment\");\n }\n\n // colon\n if (ch == \":\") {\n return rval(state,stream,\"colon\");\n }\n\n // macro\n if (ch == '?') {\n stream.eatSpace();\n stream.eatWhile(anumRE);\n return rval(state,stream,\"macro\");\n }\n\n // record\n if (ch == \"#\") {\n stream.eatSpace();\n stream.eatWhile(anumRE);\n return rval(state,stream,\"record\");\n }\n\n // dollar escape\n if (ch == \"$\") {\n if (stream.next() == \"\\\\\" && !stream.match(escapesRE)) {\n return rval(state,stream,\"error\");\n }\n return rval(state,stream,\"number\");\n }\n\n // dot\n if (ch == \".\") {\n return rval(state,stream,\"dot\");\n }\n\n // quoted atom\n if (ch == '\\'') {\n if (!(state.in_atom = (!singleQuote(stream)))) {\n if (stream.match(/\\s*\\/\\s*[0-9]/,false)) {\n stream.match(/\\s*\\/\\s*[0-9]/,true);\n return rval(state,stream,\"fun\"); // 'f'/0 style fun\n }\n if (stream.match(/\\s*\\(/,false) || stream.match(/\\s*:/,false)) {\n return rval(state,stream,\"function\");\n }\n }\n return rval(state,stream,\"atom\");\n }\n\n // string\n if (ch == '\"') {\n state.in_string = (!doubleQuote(stream));\n return rval(state,stream,\"string\");\n }\n\n // variable\n if (/[A-Z_Ø-ÞÀ-Ö]/.test(ch)) {\n stream.eatWhile(anumRE);\n return rval(state,stream,\"variable\");\n }\n\n // atom/keyword/BIF/function\n if (/[a-z_ß-öø-ÿ]/.test(ch)) {\n stream.eatWhile(anumRE);\n\n if (stream.match(/\\s*\\/\\s*[0-9]/,false)) {\n stream.match(/\\s*\\/\\s*[0-9]/,true);\n return rval(state,stream,\"fun\"); // f/0 style fun\n }\n\n var w = stream.current();\n\n if (is_member(w,keywordWords)) {\n return rval(state,stream,\"keyword\");\n }else if (is_member(w,operatorAtomWords)) {\n return rval(state,stream,\"operator\");\n }else if (stream.match(/\\s*\\(/,false)) {\n // 'put' and 'erlang:put' are bifs, 'foo:put' is not\n if (is_member(w,bifWords) &&\n ((peekToken(state).token != \":\") ||\n (peekToken(state,2).token == \"erlang\"))) {\n return rval(state,stream,\"builtin\");\n }else if (is_member(w,guardWords)) {\n return rval(state,stream,\"guard\");\n }else{\n return rval(state,stream,\"function\");\n }\n }else if (lookahead(stream) == \":\") {\n if (w == \"erlang\") {\n return rval(state,stream,\"builtin\");\n } else {\n return rval(state,stream,\"function\");\n }\n }else if (is_member(w,[\"true\",\"false\"])) {\n return rval(state,stream,\"boolean\");\n }else{\n return rval(state,stream,\"atom\");\n }\n }\n\n // number\n var digitRE = /[0-9]/;\n var radixRE = /[0-9a-zA-Z]/; // 36#zZ style int\n if (digitRE.test(ch)) {\n stream.eatWhile(digitRE);\n if (stream.eat('#')) { // 36#aZ style integer\n if (!stream.eatWhile(radixRE)) {\n stream.backUp(1); //\"36#\" - syntax error\n }\n } else if (stream.eat('.')) { // float\n if (!stream.eatWhile(digitRE)) {\n stream.backUp(1); // \"3.\" - probably end of function\n } else {\n if (stream.eat(/[eE]/)) { // float with exponent\n if (stream.eat(/[-+]/)) {\n if (!stream.eatWhile(digitRE)) {\n stream.backUp(2); // \"2e-\" - syntax error\n }\n } else {\n if (!stream.eatWhile(digitRE)) {\n stream.backUp(1); // \"2e\" - syntax error\n }\n }\n }\n }\n }\n return rval(state,stream,\"number\"); // normal integer\n }\n\n // open parens\n if (nongreedy(stream,openParenRE,openParenWords)) {\n return rval(state,stream,\"open_paren\");\n }\n\n // close parens\n if (nongreedy(stream,closeParenRE,closeParenWords)) {\n return rval(state,stream,\"close_paren\");\n }\n\n // separators\n if (greedy(stream,separatorRE,separatorWords)) {\n return rval(state,stream,\"separator\");\n }\n\n // operators\n if (greedy(stream,operatorSymbolRE,operatorSymbolWords)) {\n return rval(state,stream,\"operator\");\n }\n\n return rval(state,stream,null);\n}\n\n/////////////////////////////////////////////////////////////////////////////\n// utilities\nfunction nongreedy(stream,re,words) {\n if (stream.current().length == 1 && re.test(stream.current())) {\n stream.backUp(1);\n while (re.test(stream.peek())) {\n stream.next();\n if (is_member(stream.current(),words)) {\n return true;\n }\n }\n stream.backUp(stream.current().length-1);\n }\n return false;\n}\n\nfunction greedy(stream,re,words) {\n if (stream.current().length == 1 && re.test(stream.current())) {\n while (re.test(stream.peek())) {\n stream.next();\n }\n while (0 < stream.current().length) {\n if (is_member(stream.current(),words)) {\n return true;\n }else{\n stream.backUp(1);\n }\n }\n stream.next();\n }\n return false;\n}\n\nfunction doubleQuote(stream) {\n return quote(stream, '\"', '\\\\');\n}\n\nfunction singleQuote(stream) {\n return quote(stream,'\\'','\\\\');\n}\n\nfunction quote(stream,quoteChar,escapeChar) {\n while (!stream.eol()) {\n var ch = stream.next();\n if (ch == quoteChar) {\n return true;\n }else if (ch == escapeChar) {\n stream.next();\n }\n }\n return false;\n}\n\nfunction lookahead(stream) {\n var m = stream.match(/^\\s*([^\\s%])/, false)\n return m ? m[1] : \"\";\n}\n\nfunction is_member(element,list) {\n return (-1 < list.indexOf(element));\n}\n\nfunction rval(state,stream,type) {\n\n // parse stack\n pushToken(state,realToken(type,stream));\n\n // map erlang token type to CodeMirror style class\n // erlang -> CodeMirror tag\n switch (type) {\n case \"atom\": return \"atom\";\n case \"attribute\": return \"attribute\";\n case \"boolean\": return \"atom\";\n case \"builtin\": return \"builtin\";\n case \"close_paren\": return null;\n case \"colon\": return null;\n case \"comment\": return \"comment\";\n case \"dot\": return null;\n case \"error\": return \"error\";\n case \"fun\": return \"meta\";\n case \"function\": return \"tag\";\n case \"guard\": return \"property\";\n case \"keyword\": return \"keyword\";\n case \"macro\": return \"macroName\";\n case \"number\": return \"number\";\n case \"open_paren\": return null;\n case \"operator\": return \"operator\";\n case \"record\": return \"bracket\";\n case \"separator\": return null;\n case \"string\": return \"string\";\n case \"type\": return \"def\";\n case \"variable\": return \"variable\";\n default: return null;\n }\n}\n\nfunction aToken(tok,col,ind,typ) {\n return {token: tok,\n column: col,\n indent: ind,\n type: typ};\n}\n\nfunction realToken(type,stream) {\n return aToken(stream.current(),\n stream.column(),\n stream.indentation(),\n type);\n}\n\nfunction fakeToken(type) {\n return aToken(type,0,0,type);\n}\n\nfunction peekToken(state,depth) {\n var len = state.tokenStack.length;\n var dep = (depth ? depth : 1);\n\n if (len < dep) {\n return false;\n }else{\n return state.tokenStack[len-dep];\n }\n}\n\nfunction pushToken(state,token) {\n\n if (!(token.type == \"comment\" || token.type == \"whitespace\")) {\n state.tokenStack = maybe_drop_pre(state.tokenStack,token);\n state.tokenStack = maybe_drop_post(state.tokenStack);\n }\n}\n\nfunction maybe_drop_pre(s,token) {\n var last = s.length-1;\n\n if (0 < last && s[last].type === \"record\" && token.type === \"dot\") {\n s.pop();\n }else if (0 < last && s[last].type === \"group\") {\n s.pop();\n s.push(token);\n }else{\n s.push(token);\n }\n return s;\n}\n\nfunction maybe_drop_post(s) {\n if (!s.length) return s\n var last = s.length-1;\n\n if (s[last].type === \"dot\") {\n return [];\n }\n if (last > 1 && s[last].type === \"fun\" && s[last-1].token === \"fun\") {\n return s.slice(0,last-1);\n }\n switch (s[last].token) {\n case \"}\": return d(s,{g:[\"{\"]});\n case \"]\": return d(s,{i:[\"[\"]});\n case \")\": return d(s,{i:[\"(\"]});\n case \">>\": return d(s,{i:[\"<<\"]});\n case \"end\": return d(s,{i:[\"begin\",\"case\",\"fun\",\"if\",\"receive\",\"try\"]});\n case \",\": return d(s,{e:[\"begin\",\"try\",\"when\",\"->\",\n \",\",\"(\",\"[\",\"{\",\"<<\"]});\n case \"->\": return d(s,{r:[\"when\"],\n m:[\"try\",\"if\",\"case\",\"receive\"]});\n case \";\": return d(s,{E:[\"case\",\"fun\",\"if\",\"receive\",\"try\",\"when\"]});\n case \"catch\":return d(s,{e:[\"try\"]});\n case \"of\": return d(s,{e:[\"case\"]});\n case \"after\":return d(s,{e:[\"receive\",\"try\"]});\n default: return s;\n }\n}\n\nfunction d(stack,tt) {\n // stack is a stack of Token objects.\n // tt is an object; {type:tokens}\n // type is a char, tokens is a list of token strings.\n // The function returns (possibly truncated) stack.\n // It will descend the stack, looking for a Token such that Token.token\n // is a member of tokens. If it does not find that, it will normally (but\n // see \"E\" below) return stack. If it does find a match, it will remove\n // all the Tokens between the top and the matched Token.\n // If type is \"m\", that is all it does.\n // If type is \"i\", it will also remove the matched Token and the top Token.\n // If type is \"g\", like \"i\", but add a fake \"group\" token at the top.\n // If type is \"r\", it will remove the matched Token, but not the top Token.\n // If type is \"e\", it will keep the matched Token but not the top Token.\n // If type is \"E\", it behaves as for type \"e\", except if there is no match,\n // in which case it will return an empty stack.\n\n for (var type in tt) {\n var len = stack.length-1;\n var tokens = tt[type];\n for (var i = len-1; -1 < i ; i--) {\n if (is_member(stack[i].token,tokens)) {\n var ss = stack.slice(0,i);\n switch (type) {\n case \"m\": return ss.concat(stack[i]).concat(stack[len]);\n case \"r\": return ss.concat(stack[len]);\n case \"i\": return ss;\n case \"g\": return ss.concat(fakeToken(\"group\"));\n case \"E\": return ss.concat(stack[i]);\n case \"e\": return ss.concat(stack[i]);\n }\n }\n }\n }\n return (type == \"E\" ? [] : stack);\n}\n\n/////////////////////////////////////////////////////////////////////////////\n// indenter\n\nfunction indenter(state, textAfter, cx) {\n var t;\n var wordAfter = wordafter(textAfter);\n var currT = peekToken(state,1);\n var prevT = peekToken(state,2);\n\n if (state.in_string || state.in_atom) {\n return null;\n }else if (!prevT) {\n return 0;\n }else if (currT.token == \"when\") {\n return currT.column + cx.unit;\n }else if (wordAfter === \"when\" && prevT.type === \"function\") {\n return prevT.indent+cx.unit;\n }else if (wordAfter === \"(\" && currT.token === \"fun\") {\n return currT.column+3;\n }else if (wordAfter === \"catch\" && (t = getToken(state,[\"try\"]))) {\n return t.column;\n }else if (is_member(wordAfter,[\"end\",\"after\",\"of\"])) {\n t = getToken(state,[\"begin\",\"case\",\"fun\",\"if\",\"receive\",\"try\"]);\n return t ? t.column : null;\n }else if (is_member(wordAfter,closeParenWords)) {\n t = getToken(state,openParenWords);\n return t ? t.column : null;\n }else if (is_member(currT.token,[\",\",\"|\",\"||\"]) ||\n is_member(wordAfter,[\",\",\"|\",\"||\"])) {\n t = postcommaToken(state);\n return t ? t.column+t.token.length : cx.unit;\n }else if (currT.token == \"->\") {\n if (is_member(prevT.token, [\"receive\",\"case\",\"if\",\"try\"])) {\n return prevT.column+cx.unit+cx.unit;\n }else{\n return prevT.column+cx.unit;\n }\n }else if (is_member(currT.token,openParenWords)) {\n return currT.column+currT.token.length;\n }else{\n t = defaultToken(state);\n return truthy(t) ? t.column+cx.unit : 0;\n }\n}\n\nfunction wordafter(str) {\n var m = str.match(/,|[a-z]+|\\}|\\]|\\)|>>|\\|+|\\(/);\n\n return truthy(m) && (m.index === 0) ? m[0] : \"\";\n}\n\nfunction postcommaToken(state) {\n var objs = state.tokenStack.slice(0,-1);\n var i = getTokenIndex(objs,\"type\",[\"open_paren\"]);\n\n return truthy(objs[i]) ? objs[i] : false;\n}\n\nfunction defaultToken(state) {\n var objs = state.tokenStack;\n var stop = getTokenIndex(objs,\"type\",[\"open_paren\",\"separator\",\"keyword\"]);\n var oper = getTokenIndex(objs,\"type\",[\"operator\"]);\n\n if (truthy(stop) && truthy(oper) && stop < oper) {\n return objs[stop+1];\n } else if (truthy(stop)) {\n return objs[stop];\n } else {\n return false;\n }\n}\n\nfunction getToken(state,tokens) {\n var objs = state.tokenStack;\n var i = getTokenIndex(objs,\"token\",tokens);\n\n return truthy(objs[i]) ? objs[i] : false;\n}\n\nfunction getTokenIndex(objs,propname,propvals) {\n\n for (var i = objs.length-1; -1 < i ; i--) {\n if (is_member(objs[i][propname],propvals)) {\n return i;\n }\n }\n return false;\n}\n\nfunction truthy(x) {\n return (x !== false) && (x != null);\n}\n\n/////////////////////////////////////////////////////////////////////////////\n// this object defines the mode\n\nexport const erlang = {\n name: \"erlang\",\n startState() {\n return {tokenStack: [],\n in_string: false,\n in_atom: false};\n },\n\n token: tokenizer,\n\n indent: indenter,\n\n languageData: {\n commentTokens: {line: \"%\"}\n }\n};\n\n"],"names":["typeWords","keywordWords","separatorRE","separatorWords","operatorAtomWords","operatorSymbolRE","operatorSymbolWords","openParenRE","openParenWords","closeParenRE","closeParenWords","guardWords","bifWords","anumRE","escapesRE","nongreedy","stream","re","words","current","length","test","backUp","peek","next","is_member","greedy","doubleQuote","quote","singleQuote","quoteChar","escapeChar","eol","ch","element","list","indexOf","rval","state","type","token","tokenStack","s","last","pop","push","maybe_drop_pre","slice","d","g","i","e","r","m","E","maybe_drop_post","pushToken","aToken","column","indentation","realToken","tok","col","ind","typ","indent","fakeToken","peekToken","depth","len","dep","stack","tt","tokens","ss","concat","getToken","objs","getTokenIndex","truthy","propname","propvals","x","erlang","name","startState","in_string","in_atom","eatSpace","match","skipToEnd","eatWhile","w","lookahead","digitRE","eat","textAfter","cx","t","wordAfter","index","currT","prevT","unit","postcommaToken","stop","oper","defaultToken","languageData","commentTokens","line"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/3747.index.js b/book/_build/html/_static/3747.index.js
new file mode 100644
index 0000000..ccc68da
--- /dev/null
+++ b/book/_build/html/_static/3747.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[3747],{3747:(e,t,r)=>{function n(e){var t,r,n=e.statementIndent,a=e.jsonld,i=e.json||a,o=e.typescript,u=e.wordCharacters||/[\w$\xa1-\uffff]/,s=function(){function e(e){return{type:e,style:"keyword"}}var t=e("keyword a"),r=e("keyword b"),n=e("keyword c"),a=e("keyword d"),i=e("operator"),o={type:"atom",style:"atom"};return{if:e("if"),while:t,with:t,else:r,do:r,try:r,finally:r,return:a,break:a,continue:a,new:e("new"),delete:n,void:n,throw:n,debugger:e("debugger"),var:e("var"),const:e("var"),let:e("var"),function:e("function"),catch:e("catch"),for:e("for"),switch:e("switch"),case:e("case"),default:e("default"),in:i,typeof:i,instanceof:i,true:o,false:o,null:o,undefined:o,NaN:o,Infinity:o,this:e("this"),class:e("class"),super:e("atom"),yield:n,export:e("export"),import:e("import"),extends:n,await:n}}(),c=/[+\-*&%=<>!?|~^@]/,l=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;function f(e,n,a){return t=e,r=a,n}function d(e,t){var r,n=e.next();if('"'==n||"'"==n)return t.tokenize=(r=n,function(e,t){var n,i=!1;if(a&&"@"==e.peek()&&e.match(l))return t.tokenize=d,f("jsonld-keyword","meta");for(;null!=(n=e.next())&&(n!=r||i);)i=!i&&"\\"==n;return i||(t.tokenize=d),f("string","string")}),t.tokenize(e,t);if("."==n&&e.match(/^\d[\d_]*(?:[eE][+\-]?[\d_]+)?/))return f("number","number");if("."==n&&e.match(".."))return f("spread","meta");if(/[\[\]{}\(\),;\:\.]/.test(n))return f(n);if("="==n&&e.eat(">"))return f("=>","operator");if("0"==n&&e.match(/^(?:x[\dA-Fa-f_]+|o[0-7_]+|b[01_]+)n?/))return f("number","number");if(/\d/.test(n))return e.match(/^[\d_]*(?:n|(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)?/),f("number","number");if("/"==n)return e.eat("*")?(t.tokenize=m,m(e,t)):e.eat("/")?(e.skipToEnd(),f("comment","comment")):function(e,t,r){return t.tokenize==d&&/^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(t.lastType)||"quasi"==t.lastType&&/\{\s*$/.test(e.string.slice(0,e.pos-1))}(e,t)?(function(e){for(var t,r=!1,n=!1;null!=(t=e.next());){if(!r){if("/"==t&&!n)return;"["==t?n=!0:n&&"]"==t&&(n=!1)}r=!r&&"\\"==t}}(e),e.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/),f("regexp","string.special")):(e.eat("="),f("operator","operator",e.current()));if("`"==n)return t.tokenize=p,p(e,t);if("#"==n&&"!"==e.peek())return e.skipToEnd(),f("meta","meta");if("#"==n&&e.eatWhile(u))return f("variable","property");if("<"==n&&e.match("!--")||"-"==n&&e.match("->")&&!/\S/.test(e.string.slice(0,e.start)))return e.skipToEnd(),f("comment","comment");if(c.test(n))return">"==n&&t.lexical&&">"==t.lexical.type||(e.eat("=")?"!"!=n&&"="!=n||e.eat("="):/[<>*+\-|&?]/.test(n)&&(e.eat(n),">"==n&&e.eat(n))),"?"==n&&e.eat(".")?f("."):f("operator","operator",e.current());if(u.test(n)){e.eatWhile(u);var i=e.current();if("."!=t.lastType){if(s.propertyIsEnumerable(i)){var o=s[i];return f(o.type,o.style,i)}if("async"==i&&e.match(/^(\s|\/\*([^*]|\*(?!\/))*?\*\/)*[\[\(\w]/,!1))return f("async","keyword",i)}return f("variable","variable",i)}}function m(e,t){for(var r,n=!1;r=e.next();){if("/"==r&&n){t.tokenize=d;break}n="*"==r}return f("comment","comment")}function p(e,t){for(var r,n=!1;null!=(r=e.next());){if(!n&&("`"==r||"$"==r&&e.eat("{"))){t.tokenize=d;break}n=!n&&"\\"==r}return f("quasi","string.special",e.current())}var k="([{}])";function v(e,t){t.fatArrowAt&&(t.fatArrowAt=null);var r=e.string.indexOf("=>",e.start);if(!(r<0)){if(o){var n=/:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(e.string.slice(e.start,r));n&&(r=n.index)}for(var a=0,i=!1,s=r-1;s>=0;--s){var c=e.string.charAt(s),l=k.indexOf(c);if(l>=0&&l<3){if(!a){++s;break}if(0==--a){"("==c&&(i=!0);break}}else if(l>=3&&l<6)++a;else if(u.test(c))i=!0;else if(/["'\/`]/.test(c))for(;;--s){if(0==s)return;if(e.string.charAt(s-1)==c&&"\\"!=e.string.charAt(s-2)){s--;break}}else if(i&&!a){++s;break}}i&&!a&&(t.fatArrowAt=s)}}var y={atom:!0,number:!0,variable:!0,string:!0,regexp:!0,this:!0,import:!0,"jsonld-keyword":!0};function w(e,t,r,n,a,i){this.indented=e,this.column=t,this.type=r,this.prev=a,this.info=i,null!=n&&(this.align=n)}function b(e,t){for(var r=e.localVars;r;r=r.next)if(r.name==t)return!0;for(var n=e.context;n;n=n.prev)for(r=n.vars;r;r=r.next)if(r.name==t)return!0}var h={state:null,column:null,marked:null,cc:null};function x(){for(var e=arguments.length-1;e>=0;e--)h.cc.push(arguments[e])}function g(){return x.apply(null,arguments),!0}function V(e,t){for(var r=t;r;r=r.next)if(r.name==e)return!0;return!1}function A(t){var r=h.state;if(h.marked="def",r.context)if("var"==r.lexical.info&&r.context&&r.context.block){var n=z(t,r.context);if(null!=n)return void(r.context=n)}else if(!V(t,r.localVars))return void(r.localVars=new $(t,r.localVars));e.globalVars&&!V(t,r.globalVars)&&(r.globalVars=new $(t,r.globalVars))}function z(e,t){if(t){if(t.block){var r=z(e,t.prev);return r?r==t.prev?t:new T(r,t.vars,!0):null}return V(e,t.vars)?t:new T(t.prev,new $(e,t.vars),!1)}return null}function j(e){return"public"==e||"private"==e||"protected"==e||"abstract"==e||"readonly"==e}function T(e,t,r){this.prev=e,this.vars=t,this.block=r}function $(e,t){this.name=e,this.next=t}var O=new $("this",new $("arguments",null));function _(){h.state.context=new T(h.state.context,h.state.localVars,!1),h.state.localVars=O}function q(){h.state.context=new T(h.state.context,h.state.localVars,!0),h.state.localVars=null}function E(){h.state.localVars=h.state.context.vars,h.state.context=h.state.context.prev}function I(e,t){var r=function(){var r=h.state,n=r.indented;if("stat"==r.lexical.type)n=r.lexical.indented;else for(var a=r.lexical;a&&")"==a.type&&a.align;a=a.prev)n=a.indented;r.lexical=new w(n,h.stream.column(),e,null,r.lexical,t)};return r.lex=!0,r}function C(){var e=h.state;e.lexical.prev&&(")"==e.lexical.type&&(e.indented=e.lexical.indented),e.lexical=e.lexical.prev)}function S(e){return function t(r){return r==e?g():";"==e||"}"==r||")"==r||"]"==r?x():g(t)}}function N(e,t){return"var"==e?g(I("vardef",t),he,S(";"),C):"keyword a"==e?g(I("form"),D,N,C):"keyword b"==e?g(I("form"),N,C):"keyword d"==e?h.stream.match(/^\s*$/,!1)?g():g(I("stat"),U,S(";"),C):"debugger"==e?g(S(";")):"{"==e?g(I("}"),q,ae,C,E):";"==e?g():"if"==e?("else"==h.state.lexical.info&&h.state.cc[h.state.cc.length-1]==C&&h.state.cc.pop()(),g(I("form"),D,N,C,je)):"function"==e?g(_e):"for"==e?g(I("form"),q,Te,N,E,C):"class"==e||o&&"interface"==t?(h.marked="keyword",g(I("form","class"==e?e:t),Se,C)):"variable"==e?o&&"declare"==t?(h.marked="keyword",g(N)):o&&("module"==t||"enum"==t||"type"==t)&&h.stream.match(/^\s*\w/,!1)?(h.marked="keyword","enum"==t?g(Le):"type"==t?g(Ee,S("operator"),ce,S(";")):g(I("form"),xe,S("{"),I("}"),ae,C,C)):o&&"namespace"==t?(h.marked="keyword",g(I("form"),W,N,C)):o&&"abstract"==t?(h.marked="keyword",g(N)):g(I("stat"),X):"switch"==e?g(I("form"),D,S("{"),I("}","switch"),q,ae,C,C,E):"case"==e?g(W,S(":")):"default"==e?g(S(":")):"catch"==e?g(I("form"),_,P,N,C,E):"export"==e?g(I("stat"),Be,C):"import"==e?g(I("stat"),Fe,C):"async"==e?g(N):"@"==t?g(W,N):x(I("stat"),W,S(";"),C)}function P(e){if("("==e)return g(Ie,S(")"))}function W(e,t){return F(e,t,!1)}function B(e,t){return F(e,t,!0)}function D(e){return"("!=e?x():g(I(")"),U,S(")"),C)}function F(e,t,r){if(h.state.fatArrowAt==h.stream.start){var n=r?M:L;if("("==e)return g(_,I(")"),re(Ie,")"),C,S("=>"),n,E);if("variable"==e)return x(_,xe,S("=>"),n,E)}var a=r?H:G;return y.hasOwnProperty(e)?g(a):"function"==e?g(_e,a):"class"==e||o&&"interface"==t?(h.marked="keyword",g(I("form"),Ce,C)):"keyword c"==e||"async"==e?g(r?B:W):"("==e?g(I(")"),U,S(")"),C,a):"operator"==e||"spread"==e?g(r?B:W):"["==e?g(I("]"),Ke,C,a):"{"==e?ne(Z,"}",null,a):"quasi"==e?x(J,a):"new"==e?g(function(e){return function(t){return"."==t?g(e?R:Q):"variable"==t&&o?g(ye,e?H:G):x(e?B:W)}}(r)):g()}function U(e){return e.match(/[;\}\)\],]/)?x():x(W)}function G(e,t){return","==e?g(U):H(e,t,!1)}function H(e,t,r){var n=0==r?G:H,a=0==r?W:B;return"=>"==e?g(_,r?M:L,E):"operator"==e?/\+\+|--/.test(t)||o&&"!"==t?g(n):o&&"<"==t&&h.stream.match(/^([^<>]|<[^<>]*>)*>\s*\(/,!1)?g(I(">"),re(ce,">"),C,n):"?"==t?g(W,S(":"),a):g(a):"quasi"==e?x(J,n):";"!=e?"("==e?ne(B,")","call",n):"."==e?g(Y,n):"["==e?g(I("]"),U,S("]"),C,n):o&&"as"==t?(h.marked="keyword",g(ce,n)):"regexp"==e?(h.state.lastType=h.marked="operator",h.stream.backUp(h.stream.pos-h.stream.start-1),g(a)):void 0:void 0}function J(e,t){return"quasi"!=e?x():"${"!=t.slice(t.length-2)?g(J):g(U,K)}function K(e){if("}"==e)return h.marked="string.special",h.state.tokenize=p,g(J)}function L(e){return v(h.stream,h.state),x("{"==e?N:W)}function M(e){return v(h.stream,h.state),x("{"==e?N:B)}function Q(e,t){if("target"==t)return h.marked="keyword",g(G)}function R(e,t){if("target"==t)return h.marked="keyword",g(H)}function X(e){return":"==e?g(C,N):x(G,S(";"),C)}function Y(e){if("variable"==e)return h.marked="property",g()}function Z(e,t){return"async"==e?(h.marked="property",g(Z)):"variable"==e||"keyword"==h.style?(h.marked="property","get"==t||"set"==t?g(ee):(o&&h.state.fatArrowAt==h.stream.start&&(r=h.stream.match(/^\s*:\s*/,!1))&&(h.state.fatArrowAt=h.stream.pos+r[0].length),g(te))):"number"==e||"string"==e?(h.marked=a?"property":h.style+" property",g(te)):"jsonld-keyword"==e?g(te):o&&j(t)?(h.marked="keyword",g(Z)):"["==e?g(W,ie,S("]"),te):"spread"==e?g(B,te):"*"==t?(h.marked="keyword",g(Z)):":"==e?x(te):void 0;var r}function ee(e){return"variable"!=e?x(te):(h.marked="property",g(_e))}function te(e){return":"==e?g(B):"("==e?x(_e):void 0}function re(e,t,r){function n(a,i){if(r?r.indexOf(a)>-1:","==a){var o=h.state.lexical;return"call"==o.info&&(o.pos=(o.pos||0)+1),g((function(r,n){return r==t||n==t?x():x(e)}),n)}return a==t||i==t?g():r&&r.indexOf(";")>-1?x(e):g(S(t))}return function(r,a){return r==t||a==t?g():x(e,n)}}function ne(e,t,r){for(var n=3;n"),ce):"quasi"==e?x(me,ve):void 0}function le(e){if("=>"==e)return g(ce)}function fe(e){return e.match(/[\}\)\]]/)?g():","==e||";"==e?g(fe):x(de,fe)}function de(e,t){return"variable"==e||"keyword"==h.style?(h.marked="property",g(de)):"?"==t||"number"==e||"string"==e?g(de):":"==e?g(ce):"["==e?g(S("variable"),oe,S("]"),de):"("==e?x(qe,de):e.match(/[;\}\)\],]/)?void 0:g()}function me(e,t){return"quasi"!=e?x():"${"!=t.slice(t.length-2)?g(me):g(ce,pe)}function pe(e){if("}"==e)return h.marked="string.special",h.state.tokenize=p,g(me)}function ke(e,t){return"variable"==e&&h.stream.match(/^\s*[?:]/,!1)||"?"==t?g(ke):":"==e?g(ce):"spread"==e?g(ke):x(ce)}function ve(e,t){return"<"==t?g(I(">"),re(ce,">"),C,ve):"|"==t||"."==e||"&"==t?g(ce):"["==e?g(ce,S("]"),ve):"extends"==t||"implements"==t?(h.marked="keyword",g(ce)):"?"==t?g(ce,S(":"),ce):void 0}function ye(e,t){if("<"==t)return g(I(">"),re(ce,">"),C,ve)}function we(){return x(ce,be)}function be(e,t){if("="==t)return g(ce)}function he(e,t){return"enum"==t?(h.marked="keyword",g(Le)):x(xe,ie,Ae,ze)}function xe(e,t){return o&&j(t)?(h.marked="keyword",g(xe)):"variable"==e?(A(t),g()):"spread"==e?g(xe):"["==e?ne(Ve,"]"):"{"==e?ne(ge,"}"):void 0}function ge(e,t){return"variable"!=e||h.stream.match(/^\s*:/,!1)?("variable"==e&&(h.marked="property"),"spread"==e?g(xe):"}"==e?x():"["==e?g(W,S("]"),S(":"),ge):g(S(":"),xe,Ae)):(A(t),g(Ae))}function Ve(){return x(xe,Ae)}function Ae(e,t){if("="==t)return g(B)}function ze(e){if(","==e)return g(he)}function je(e,t){if("keyword b"==e&&"else"==t)return g(I("form","else"),N,C)}function Te(e,t){return"await"==t?g(Te):"("==e?g(I(")"),$e,C):void 0}function $e(e){return"var"==e?g(he,Oe):"variable"==e?g(Oe):x(Oe)}function Oe(e,t){return")"==e?g():";"==e?g(Oe):"in"==t||"of"==t?(h.marked="keyword",g(W,Oe)):x(W,Oe)}function _e(e,t){return"*"==t?(h.marked="keyword",g(_e)):"variable"==e?(A(t),g(_e)):"("==e?g(_,I(")"),re(Ie,")"),C,ue,N,E):o&&"<"==t?g(I(">"),re(we,">"),C,_e):void 0}function qe(e,t){return"*"==t?(h.marked="keyword",g(qe)):"variable"==e?(A(t),g(qe)):"("==e?g(_,I(")"),re(Ie,")"),C,ue,E):o&&"<"==t?g(I(">"),re(we,">"),C,qe):void 0}function Ee(e,t){return"keyword"==e||"variable"==e?(h.marked="type",g(Ee)):"<"==t?g(I(">"),re(we,">"),C):void 0}function Ie(e,t){return"@"==t&&g(W,Ie),"spread"==e?g(Ie):o&&j(t)?(h.marked="keyword",g(Ie)):o&&"this"==e?g(ie,Ae):x(xe,ie,Ae)}function Ce(e,t){return"variable"==e?Se(e,t):Ne(e,t)}function Se(e,t){if("variable"==e)return A(t),g(Ne)}function Ne(e,t){return"<"==t?g(I(">"),re(we,">"),C,Ne):"extends"==t||"implements"==t||o&&","==e?("implements"==t&&(h.marked="keyword"),g(o?ce:W,Ne)):"{"==e?g(I("}"),Pe,C):void 0}function Pe(e,t){return"async"==e||"variable"==e&&("static"==t||"get"==t||"set"==t||o&&j(t))&&h.stream.match(/^\s+#?[\w$\xa1-\uffff]/,!1)?(h.marked="keyword",g(Pe)):"variable"==e||"keyword"==h.style?(h.marked="property",g(We,Pe)):"number"==e||"string"==e?g(We,Pe):"["==e?g(W,ie,S("]"),We,Pe):"*"==t?(h.marked="keyword",g(Pe)):o&&"("==e?x(qe,Pe):";"==e||","==e?g(Pe):"}"==e?g():"@"==t?g(W,Pe):void 0}function We(e,t){if("!"==t||"?"==t)return g(We);if(":"==e)return g(ce,Ae);if("="==t)return g(B);var r=h.state.lexical.prev;return x(r&&"interface"==r.info?qe:_e)}function Be(e,t){return"*"==t?(h.marked="keyword",g(Je,S(";"))):"default"==t?(h.marked="keyword",g(W,S(";"))):"{"==e?g(re(De,"}"),Je,S(";")):x(N)}function De(e,t){return"as"==t?(h.marked="keyword",g(S("variable"))):"variable"==e?x(B,De):void 0}function Fe(e){return"string"==e?g():"("==e?x(W):"."==e?x(G):x(Ue,Ge,Je)}function Ue(e,t){return"{"==e?ne(Ue,"}"):("variable"==e&&A(t),"*"==t&&(h.marked="keyword"),g(He))}function Ge(e){if(","==e)return g(Ue,Ge)}function He(e,t){if("as"==t)return h.marked="keyword",g(Ue)}function Je(e,t){if("from"==t)return h.marked="keyword",g(W)}function Ke(e){return"]"==e?g():x(re(B,"]"))}function Le(){return x(I("form"),xe,S("{"),I("}"),re(Me,"}"),C,C)}function Me(){return x(xe,Ae)}return _.lex=q.lex=!0,E.lex=!0,C.lex=!0,{name:e.name,startState:function(t){var r={tokenize:d,lastType:"sof",cc:[],lexical:new w(-t,0,"block",!1),localVars:e.localVars,context:e.localVars&&new T(null,null,!1),indented:0};return e.globalVars&&"object"==typeof e.globalVars&&(r.globalVars=e.globalVars),r},token:function(e,n){if(e.sol()&&(n.lexical.hasOwnProperty("align")||(n.lexical.align=!1),n.indented=e.indentation(),v(e,n)),n.tokenize!=m&&e.eatSpace())return null;var a=n.tokenize(e,n);return"comment"==t?a:(n.lastType="operator"!=t||"++"!=r&&"--"!=r?t:"incdec",function(e,t,r,n,a){var o=e.cc;for(h.state=e,h.stream=a,h.marked=null,h.cc=o,h.style=t,e.lexical.hasOwnProperty("align")||(e.lexical.align=!0);;)if((o.length?o.pop():i?W:N)(r,n)){for(;o.length&&o[o.length-1].lex;)o.pop()();return h.marked?h.marked:"variable"==r&&b(e,n)?"variableName.local":t}}(n,a,t,r,e))},indent:function(t,r,a){if(t.tokenize==m||t.tokenize==p)return null;if(t.tokenize!=d)return 0;var i,o=r&&r.charAt(0),u=t.lexical;if(!/^\s*else\b/.test(r))for(var s=t.cc.length-1;s>=0;--s){var l=t.cc[s];if(l==C)u=u.prev;else if(l!=je&&l!=E)break}for(;("stat"==u.type||"form"==u.type)&&("}"==o||(i=t.cc[t.cc.length-1])&&(i==G||i==H)&&!/^[,\.=+\-*:?[\(]/.test(r));)u=u.prev;n&&")"==u.type&&"stat"==u.prev.type&&(u=u.prev);var f=u.type,k=o==f;return"vardef"==f?u.indented+("operator"==t.lastType||","==t.lastType?u.info.length+1:0):"form"==f&&"{"==o?u.indented:"form"==f?u.indented+a.unit:"stat"==f?u.indented+(function(e,t){return"operator"==e.lastType||","==e.lastType||c.test(t.charAt(0))||/[,.]/.test(t.charAt(0))}(t,r)?n||a.unit:0):"switch"!=u.info||k||0==e.doubleIndentSwitch?u.align?u.column+(k?0:1):u.indented+(k?0:a.unit):u.indented+(/^(?:case|default)\b/.test(r)?a.unit:2*a.unit)},languageData:{indentOnInput:/^\s*(?:case .*?:|default:|\{|\})$/,commentTokens:i?void 0:{line:"//",block:{open:"/*",close:"*/"}},closeBrackets:{brackets:["(","[","{","'",'"',"`"]},wordChars:"$"}}}r.r(t),r.d(t,{javascript:()=>a,json:()=>i,jsonld:()=>o,typescript:()=>u});const a=n({name:"javascript"}),i=n({name:"json",json:!0}),o=n({name:"json",jsonld:!0}),u=n({name:"typescript",typescript:!0})}}]);
+//# sourceMappingURL=3747.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/3747.index.js.map b/book/_build/html/_static/3747.index.js.map
new file mode 100644
index 0000000..5072a4a
--- /dev/null
+++ b/book/_build/html/_static/3747.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"3747.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/javascript.js"],"sourcesContent":["function mkJavaScript(parserConfig) {\n var statementIndent = parserConfig.statementIndent;\n var jsonldMode = parserConfig.jsonld;\n var jsonMode = parserConfig.json || jsonldMode;\n var isTS = parserConfig.typescript;\n var wordRE = parserConfig.wordCharacters || /[\\w$\\xa1-\\uffff]/;\n\n // Tokenizer\n\n var keywords = function(){\n function kw(type) {return {type: type, style: \"keyword\"};}\n var A = kw(\"keyword a\"), B = kw(\"keyword b\"), C = kw(\"keyword c\"), D = kw(\"keyword d\");\n var operator = kw(\"operator\"), atom = {type: \"atom\", style: \"atom\"};\n\n return {\n \"if\": kw(\"if\"), \"while\": A, \"with\": A, \"else\": B, \"do\": B, \"try\": B, \"finally\": B,\n \"return\": D, \"break\": D, \"continue\": D, \"new\": kw(\"new\"), \"delete\": C, \"void\": C, \"throw\": C,\n \"debugger\": kw(\"debugger\"), \"var\": kw(\"var\"), \"const\": kw(\"var\"), \"let\": kw(\"var\"),\n \"function\": kw(\"function\"), \"catch\": kw(\"catch\"),\n \"for\": kw(\"for\"), \"switch\": kw(\"switch\"), \"case\": kw(\"case\"), \"default\": kw(\"default\"),\n \"in\": operator, \"typeof\": operator, \"instanceof\": operator,\n \"true\": atom, \"false\": atom, \"null\": atom, \"undefined\": atom, \"NaN\": atom, \"Infinity\": atom,\n \"this\": kw(\"this\"), \"class\": kw(\"class\"), \"super\": kw(\"atom\"),\n \"yield\": C, \"export\": kw(\"export\"), \"import\": kw(\"import\"), \"extends\": C,\n \"await\": C\n };\n }();\n\n var isOperatorChar = /[+\\-*&%=<>!?|~^@]/;\n var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)\"/;\n\n function readRegexp(stream) {\n var escaped = false, next, inSet = false;\n while ((next = stream.next()) != null) {\n if (!escaped) {\n if (next == \"/\" && !inSet) return;\n if (next == \"[\") inSet = true;\n else if (inSet && next == \"]\") inSet = false;\n }\n escaped = !escaped && next == \"\\\\\";\n }\n }\n\n // Used as scratch variables to communicate multiple values without\n // consing up tons of objects.\n var type, content;\n function ret(tp, style, cont) {\n type = tp; content = cont;\n return style;\n }\n function tokenBase(stream, state) {\n var ch = stream.next();\n if (ch == '\"' || ch == \"'\") {\n state.tokenize = tokenString(ch);\n return state.tokenize(stream, state);\n } else if (ch == \".\" && stream.match(/^\\d[\\d_]*(?:[eE][+\\-]?[\\d_]+)?/)) {\n return ret(\"number\", \"number\");\n } else if (ch == \".\" && stream.match(\"..\")) {\n return ret(\"spread\", \"meta\");\n } else if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n return ret(ch);\n } else if (ch == \"=\" && stream.eat(\">\")) {\n return ret(\"=>\", \"operator\");\n } else if (ch == \"0\" && stream.match(/^(?:x[\\dA-Fa-f_]+|o[0-7_]+|b[01_]+)n?/)) {\n return ret(\"number\", \"number\");\n } else if (/\\d/.test(ch)) {\n stream.match(/^[\\d_]*(?:n|(?:\\.[\\d_]*)?(?:[eE][+\\-]?[\\d_]+)?)?/);\n return ret(\"number\", \"number\");\n } else if (ch == \"/\") {\n if (stream.eat(\"*\")) {\n state.tokenize = tokenComment;\n return tokenComment(stream, state);\n } else if (stream.eat(\"/\")) {\n stream.skipToEnd();\n return ret(\"comment\", \"comment\");\n } else if (expressionAllowed(stream, state, 1)) {\n readRegexp(stream);\n stream.match(/^\\b(([gimyus])(?![gimyus]*\\2))+\\b/);\n return ret(\"regexp\", \"string.special\");\n } else {\n stream.eat(\"=\");\n return ret(\"operator\", \"operator\", stream.current());\n }\n } else if (ch == \"`\") {\n state.tokenize = tokenQuasi;\n return tokenQuasi(stream, state);\n } else if (ch == \"#\" && stream.peek() == \"!\") {\n stream.skipToEnd();\n return ret(\"meta\", \"meta\");\n } else if (ch == \"#\" && stream.eatWhile(wordRE)) {\n return ret(\"variable\", \"property\")\n } else if (ch == \"<\" && stream.match(\"!--\") ||\n (ch == \"-\" && stream.match(\"->\") && !/\\S/.test(stream.string.slice(0, stream.start)))) {\n stream.skipToEnd()\n return ret(\"comment\", \"comment\")\n } else if (isOperatorChar.test(ch)) {\n if (ch != \">\" || !state.lexical || state.lexical.type != \">\") {\n if (stream.eat(\"=\")) {\n if (ch == \"!\" || ch == \"=\") stream.eat(\"=\")\n } else if (/[<>*+\\-|&?]/.test(ch)) {\n stream.eat(ch)\n if (ch == \">\") stream.eat(ch)\n }\n }\n if (ch == \"?\" && stream.eat(\".\")) return ret(\".\")\n return ret(\"operator\", \"operator\", stream.current());\n } else if (wordRE.test(ch)) {\n stream.eatWhile(wordRE);\n var word = stream.current()\n if (state.lastType != \".\") {\n if (keywords.propertyIsEnumerable(word)) {\n var kw = keywords[word]\n return ret(kw.type, kw.style, word)\n }\n if (word == \"async\" && stream.match(/^(\\s|\\/\\*([^*]|\\*(?!\\/))*?\\*\\/)*[\\[\\(\\w]/, false))\n return ret(\"async\", \"keyword\", word)\n }\n return ret(\"variable\", \"variable\", word)\n }\n }\n\n function tokenString(quote) {\n return function(stream, state) {\n var escaped = false, next;\n if (jsonldMode && stream.peek() == \"@\" && stream.match(isJsonldKeyword)){\n state.tokenize = tokenBase;\n return ret(\"jsonld-keyword\", \"meta\");\n }\n while ((next = stream.next()) != null) {\n if (next == quote && !escaped) break;\n escaped = !escaped && next == \"\\\\\";\n }\n if (!escaped) state.tokenize = tokenBase;\n return ret(\"string\", \"string\");\n };\n }\n\n function tokenComment(stream, state) {\n var maybeEnd = false, ch;\n while (ch = stream.next()) {\n if (ch == \"/\" && maybeEnd) {\n state.tokenize = tokenBase;\n break;\n }\n maybeEnd = (ch == \"*\");\n }\n return ret(\"comment\", \"comment\");\n }\n\n function tokenQuasi(stream, state) {\n var escaped = false, next;\n while ((next = stream.next()) != null) {\n if (!escaped && (next == \"`\" || next == \"$\" && stream.eat(\"{\"))) {\n state.tokenize = tokenBase;\n break;\n }\n escaped = !escaped && next == \"\\\\\";\n }\n return ret(\"quasi\", \"string.special\", stream.current());\n }\n\n var brackets = \"([{}])\";\n // This is a crude lookahead trick to try and notice that we're\n // parsing the argument patterns for a fat-arrow function before we\n // actually hit the arrow token. It only works if the arrow is on\n // the same line as the arguments and there's no strange noise\n // (comments) in between. Fallback is to only notice when we hit the\n // arrow, and not declare the arguments as locals for the arrow\n // body.\n function findFatArrow(stream, state) {\n if (state.fatArrowAt) state.fatArrowAt = null;\n var arrow = stream.string.indexOf(\"=>\", stream.start);\n if (arrow < 0) return;\n\n if (isTS) { // Try to skip TypeScript return type declarations after the arguments\n var m = /:\\s*(?:\\w+(?:<[^>]*>|\\[\\])?|\\{[^}]*\\})\\s*$/.exec(stream.string.slice(stream.start, arrow))\n if (m) arrow = m.index\n }\n\n var depth = 0, sawSomething = false;\n for (var pos = arrow - 1; pos >= 0; --pos) {\n var ch = stream.string.charAt(pos);\n var bracket = brackets.indexOf(ch);\n if (bracket >= 0 && bracket < 3) {\n if (!depth) { ++pos; break; }\n if (--depth == 0) { if (ch == \"(\") sawSomething = true; break; }\n } else if (bracket >= 3 && bracket < 6) {\n ++depth;\n } else if (wordRE.test(ch)) {\n sawSomething = true;\n } else if (/[\"'\\/`]/.test(ch)) {\n for (;; --pos) {\n if (pos == 0) return\n var next = stream.string.charAt(pos - 1)\n if (next == ch && stream.string.charAt(pos - 2) != \"\\\\\") { pos--; break }\n }\n } else if (sawSomething && !depth) {\n ++pos;\n break;\n }\n }\n if (sawSomething && !depth) state.fatArrowAt = pos;\n }\n\n // Parser\n\n var atomicTypes = {\"atom\": true, \"number\": true, \"variable\": true, \"string\": true,\n \"regexp\": true, \"this\": true, \"import\": true, \"jsonld-keyword\": true};\n\n function JSLexical(indented, column, type, align, prev, info) {\n this.indented = indented;\n this.column = column;\n this.type = type;\n this.prev = prev;\n this.info = info;\n if (align != null) this.align = align;\n }\n\n function inScope(state, varname) {\n for (var v = state.localVars; v; v = v.next)\n if (v.name == varname) return true;\n for (var cx = state.context; cx; cx = cx.prev) {\n for (var v = cx.vars; v; v = v.next)\n if (v.name == varname) return true;\n }\n }\n\n function parseJS(state, style, type, content, stream) {\n var cc = state.cc;\n // Communicate our context to the combinators.\n // (Less wasteful than consing up a hundred closures on every call.)\n cx.state = state; cx.stream = stream; cx.marked = null; cx.cc = cc; cx.style = style;\n\n if (!state.lexical.hasOwnProperty(\"align\"))\n state.lexical.align = true;\n\n while(true) {\n var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;\n if (combinator(type, content)) {\n while(cc.length && cc[cc.length - 1].lex)\n cc.pop()();\n if (cx.marked) return cx.marked;\n if (type == \"variable\" && inScope(state, content)) return \"variableName.local\";\n return style;\n }\n }\n }\n\n // Combinator utils\n\n var cx = {state: null, column: null, marked: null, cc: null};\n function pass() {\n for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);\n }\n function cont() {\n pass.apply(null, arguments);\n return true;\n }\n function inList(name, list) {\n for (var v = list; v; v = v.next) if (v.name == name) return true\n return false;\n }\n function register(varname) {\n var state = cx.state;\n cx.marked = \"def\";\n if (state.context) {\n if (state.lexical.info == \"var\" && state.context && state.context.block) {\n // FIXME function decls are also not block scoped\n var newContext = registerVarScoped(varname, state.context)\n if (newContext != null) {\n state.context = newContext\n return\n }\n } else if (!inList(varname, state.localVars)) {\n state.localVars = new Var(varname, state.localVars)\n return\n }\n }\n // Fall through means this is global\n if (parserConfig.globalVars && !inList(varname, state.globalVars))\n state.globalVars = new Var(varname, state.globalVars)\n }\n function registerVarScoped(varname, context) {\n if (!context) {\n return null\n } else if (context.block) {\n var inner = registerVarScoped(varname, context.prev)\n if (!inner) return null\n if (inner == context.prev) return context\n return new Context(inner, context.vars, true)\n } else if (inList(varname, context.vars)) {\n return context\n } else {\n return new Context(context.prev, new Var(varname, context.vars), false)\n }\n }\n\n function isModifier(name) {\n return name == \"public\" || name == \"private\" || name == \"protected\" || name == \"abstract\" || name == \"readonly\"\n }\n\n // Combinators\n\n function Context(prev, vars, block) { this.prev = prev; this.vars = vars; this.block = block }\n function Var(name, next) { this.name = name; this.next = next }\n\n var defaultVars = new Var(\"this\", new Var(\"arguments\", null))\n function pushcontext() {\n cx.state.context = new Context(cx.state.context, cx.state.localVars, false)\n cx.state.localVars = defaultVars\n }\n function pushblockcontext() {\n cx.state.context = new Context(cx.state.context, cx.state.localVars, true)\n cx.state.localVars = null\n }\n pushcontext.lex = pushblockcontext.lex = true\n function popcontext() {\n cx.state.localVars = cx.state.context.vars\n cx.state.context = cx.state.context.prev\n }\n popcontext.lex = true\n function pushlex(type, info) {\n var result = function() {\n var state = cx.state, indent = state.indented;\n if (state.lexical.type == \"stat\") indent = state.lexical.indented;\n else for (var outer = state.lexical; outer && outer.type == \")\" && outer.align; outer = outer.prev)\n indent = outer.indented;\n state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);\n };\n result.lex = true;\n return result;\n }\n function poplex() {\n var state = cx.state;\n if (state.lexical.prev) {\n if (state.lexical.type == \")\")\n state.indented = state.lexical.indented;\n state.lexical = state.lexical.prev;\n }\n }\n poplex.lex = true;\n\n function expect(wanted) {\n function exp(type) {\n if (type == wanted) return cont();\n else if (wanted == \";\" || type == \"}\" || type == \")\" || type == \"]\") return pass();\n else return cont(exp);\n };\n return exp;\n }\n\n function statement(type, value) {\n if (type == \"var\") return cont(pushlex(\"vardef\", value), vardef, expect(\";\"), poplex);\n if (type == \"keyword a\") return cont(pushlex(\"form\"), parenExpr, statement, poplex);\n if (type == \"keyword b\") return cont(pushlex(\"form\"), statement, poplex);\n if (type == \"keyword d\") return cx.stream.match(/^\\s*$/, false) ? cont() : cont(pushlex(\"stat\"), maybeexpression, expect(\";\"), poplex);\n if (type == \"debugger\") return cont(expect(\";\"));\n if (type == \"{\") return cont(pushlex(\"}\"), pushblockcontext, block, poplex, popcontext);\n if (type == \";\") return cont();\n if (type == \"if\") {\n if (cx.state.lexical.info == \"else\" && cx.state.cc[cx.state.cc.length - 1] == poplex)\n cx.state.cc.pop()();\n return cont(pushlex(\"form\"), parenExpr, statement, poplex, maybeelse);\n }\n if (type == \"function\") return cont(functiondef);\n if (type == \"for\") return cont(pushlex(\"form\"), pushblockcontext, forspec, statement, popcontext, poplex);\n if (type == \"class\" || (isTS && value == \"interface\")) {\n cx.marked = \"keyword\"\n return cont(pushlex(\"form\", type == \"class\" ? type : value), className, poplex)\n }\n if (type == \"variable\") {\n if (isTS && value == \"declare\") {\n cx.marked = \"keyword\"\n return cont(statement)\n } else if (isTS && (value == \"module\" || value == \"enum\" || value == \"type\") && cx.stream.match(/^\\s*\\w/, false)) {\n cx.marked = \"keyword\"\n if (value == \"enum\") return cont(enumdef);\n else if (value == \"type\") return cont(typename, expect(\"operator\"), typeexpr, expect(\";\"));\n else return cont(pushlex(\"form\"), pattern, expect(\"{\"), pushlex(\"}\"), block, poplex, poplex)\n } else if (isTS && value == \"namespace\") {\n cx.marked = \"keyword\"\n return cont(pushlex(\"form\"), expression, statement, poplex)\n } else if (isTS && value == \"abstract\") {\n cx.marked = \"keyword\"\n return cont(statement)\n } else {\n return cont(pushlex(\"stat\"), maybelabel);\n }\n }\n if (type == \"switch\") return cont(pushlex(\"form\"), parenExpr, expect(\"{\"), pushlex(\"}\", \"switch\"), pushblockcontext,\n block, poplex, poplex, popcontext);\n if (type == \"case\") return cont(expression, expect(\":\"));\n if (type == \"default\") return cont(expect(\":\"));\n if (type == \"catch\") return cont(pushlex(\"form\"), pushcontext, maybeCatchBinding, statement, poplex, popcontext);\n if (type == \"export\") return cont(pushlex(\"stat\"), afterExport, poplex);\n if (type == \"import\") return cont(pushlex(\"stat\"), afterImport, poplex);\n if (type == \"async\") return cont(statement)\n if (value == \"@\") return cont(expression, statement)\n return pass(pushlex(\"stat\"), expression, expect(\";\"), poplex);\n }\n function maybeCatchBinding(type) {\n if (type == \"(\") return cont(funarg, expect(\")\"))\n }\n function expression(type, value) {\n return expressionInner(type, value, false);\n }\n function expressionNoComma(type, value) {\n return expressionInner(type, value, true);\n }\n function parenExpr(type) {\n if (type != \"(\") return pass()\n return cont(pushlex(\")\"), maybeexpression, expect(\")\"), poplex)\n }\n function expressionInner(type, value, noComma) {\n if (cx.state.fatArrowAt == cx.stream.start) {\n var body = noComma ? arrowBodyNoComma : arrowBody;\n if (type == \"(\") return cont(pushcontext, pushlex(\")\"), commasep(funarg, \")\"), poplex, expect(\"=>\"), body, popcontext);\n else if (type == \"variable\") return pass(pushcontext, pattern, expect(\"=>\"), body, popcontext);\n }\n\n var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;\n if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);\n if (type == \"function\") return cont(functiondef, maybeop);\n if (type == \"class\" || (isTS && value == \"interface\")) { cx.marked = \"keyword\"; return cont(pushlex(\"form\"), classExpression, poplex); }\n if (type == \"keyword c\" || type == \"async\") return cont(noComma ? expressionNoComma : expression);\n if (type == \"(\") return cont(pushlex(\")\"), maybeexpression, expect(\")\"), poplex, maybeop);\n if (type == \"operator\" || type == \"spread\") return cont(noComma ? expressionNoComma : expression);\n if (type == \"[\") return cont(pushlex(\"]\"), arrayLiteral, poplex, maybeop);\n if (type == \"{\") return contCommasep(objprop, \"}\", null, maybeop);\n if (type == \"quasi\") return pass(quasi, maybeop);\n if (type == \"new\") return cont(maybeTarget(noComma));\n return cont();\n }\n function maybeexpression(type) {\n if (type.match(/[;\\}\\)\\],]/)) return pass();\n return pass(expression);\n }\n\n function maybeoperatorComma(type, value) {\n if (type == \",\") return cont(maybeexpression);\n return maybeoperatorNoComma(type, value, false);\n }\n function maybeoperatorNoComma(type, value, noComma) {\n var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;\n var expr = noComma == false ? expression : expressionNoComma;\n if (type == \"=>\") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);\n if (type == \"operator\") {\n if (/\\+\\+|--/.test(value) || isTS && value == \"!\") return cont(me);\n if (isTS && value == \"<\" && cx.stream.match(/^([^<>]|<[^<>]*>)*>\\s*\\(/, false))\n return cont(pushlex(\">\"), commasep(typeexpr, \">\"), poplex, me);\n if (value == \"?\") return cont(expression, expect(\":\"), expr);\n return cont(expr);\n }\n if (type == \"quasi\") { return pass(quasi, me); }\n if (type == \";\") return;\n if (type == \"(\") return contCommasep(expressionNoComma, \")\", \"call\", me);\n if (type == \".\") return cont(property, me);\n if (type == \"[\") return cont(pushlex(\"]\"), maybeexpression, expect(\"]\"), poplex, me);\n if (isTS && value == \"as\") { cx.marked = \"keyword\"; return cont(typeexpr, me) }\n if (type == \"regexp\") {\n cx.state.lastType = cx.marked = \"operator\"\n cx.stream.backUp(cx.stream.pos - cx.stream.start - 1)\n return cont(expr)\n }\n }\n function quasi(type, value) {\n if (type != \"quasi\") return pass();\n if (value.slice(value.length - 2) != \"${\") return cont(quasi);\n return cont(maybeexpression, continueQuasi);\n }\n function continueQuasi(type) {\n if (type == \"}\") {\n cx.marked = \"string.special\";\n cx.state.tokenize = tokenQuasi;\n return cont(quasi);\n }\n }\n function arrowBody(type) {\n findFatArrow(cx.stream, cx.state);\n return pass(type == \"{\" ? statement : expression);\n }\n function arrowBodyNoComma(type) {\n findFatArrow(cx.stream, cx.state);\n return pass(type == \"{\" ? statement : expressionNoComma);\n }\n function maybeTarget(noComma) {\n return function(type) {\n if (type == \".\") return cont(noComma ? targetNoComma : target);\n else if (type == \"variable\" && isTS) return cont(maybeTypeArgs, noComma ? maybeoperatorNoComma : maybeoperatorComma)\n else return pass(noComma ? expressionNoComma : expression);\n };\n }\n function target(_, value) {\n if (value == \"target\") { cx.marked = \"keyword\"; return cont(maybeoperatorComma); }\n }\n function targetNoComma(_, value) {\n if (value == \"target\") { cx.marked = \"keyword\"; return cont(maybeoperatorNoComma); }\n }\n function maybelabel(type) {\n if (type == \":\") return cont(poplex, statement);\n return pass(maybeoperatorComma, expect(\";\"), poplex);\n }\n function property(type) {\n if (type == \"variable\") {cx.marked = \"property\"; return cont();}\n }\n function objprop(type, value) {\n if (type == \"async\") {\n cx.marked = \"property\";\n return cont(objprop);\n } else if (type == \"variable\" || cx.style == \"keyword\") {\n cx.marked = \"property\";\n if (value == \"get\" || value == \"set\") return cont(getterSetter);\n var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params\n if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\\s*:\\s*/, false)))\n cx.state.fatArrowAt = cx.stream.pos + m[0].length\n return cont(afterprop);\n } else if (type == \"number\" || type == \"string\") {\n cx.marked = jsonldMode ? \"property\" : (cx.style + \" property\");\n return cont(afterprop);\n } else if (type == \"jsonld-keyword\") {\n return cont(afterprop);\n } else if (isTS && isModifier(value)) {\n cx.marked = \"keyword\"\n return cont(objprop)\n } else if (type == \"[\") {\n return cont(expression, maybetype, expect(\"]\"), afterprop);\n } else if (type == \"spread\") {\n return cont(expressionNoComma, afterprop);\n } else if (value == \"*\") {\n cx.marked = \"keyword\";\n return cont(objprop);\n } else if (type == \":\") {\n return pass(afterprop)\n }\n }\n function getterSetter(type) {\n if (type != \"variable\") return pass(afterprop);\n cx.marked = \"property\";\n return cont(functiondef);\n }\n function afterprop(type) {\n if (type == \":\") return cont(expressionNoComma);\n if (type == \"(\") return pass(functiondef);\n }\n function commasep(what, end, sep) {\n function proceed(type, value) {\n if (sep ? sep.indexOf(type) > -1 : type == \",\") {\n var lex = cx.state.lexical;\n if (lex.info == \"call\") lex.pos = (lex.pos || 0) + 1;\n return cont(function(type, value) {\n if (type == end || value == end) return pass()\n return pass(what)\n }, proceed);\n }\n if (type == end || value == end) return cont();\n if (sep && sep.indexOf(\";\") > -1) return pass(what)\n return cont(expect(end));\n }\n return function(type, value) {\n if (type == end || value == end) return cont();\n return pass(what, proceed);\n };\n }\n function contCommasep(what, end, info) {\n for (var i = 3; i < arguments.length; i++)\n cx.cc.push(arguments[i]);\n return cont(pushlex(end, info), commasep(what, end), poplex);\n }\n function block(type) {\n if (type == \"}\") return cont();\n return pass(statement, block);\n }\n function maybetype(type, value) {\n if (isTS) {\n if (type == \":\") return cont(typeexpr);\n if (value == \"?\") return cont(maybetype);\n }\n }\n function maybetypeOrIn(type, value) {\n if (isTS && (type == \":\" || value == \"in\")) return cont(typeexpr)\n }\n function mayberettype(type) {\n if (isTS && type == \":\") {\n if (cx.stream.match(/^\\s*\\w+\\s+is\\b/, false)) return cont(expression, isKW, typeexpr)\n else return cont(typeexpr)\n }\n }\n function isKW(_, value) {\n if (value == \"is\") {\n cx.marked = \"keyword\"\n return cont()\n }\n }\n function typeexpr(type, value) {\n if (value == \"keyof\" || value == \"typeof\" || value == \"infer\" || value == \"readonly\") {\n cx.marked = \"keyword\"\n return cont(value == \"typeof\" ? expressionNoComma : typeexpr)\n }\n if (type == \"variable\" || value == \"void\") {\n cx.marked = \"type\"\n return cont(afterType)\n }\n if (value == \"|\" || value == \"&\") return cont(typeexpr)\n if (type == \"string\" || type == \"number\" || type == \"atom\") return cont(afterType);\n if (type == \"[\") return cont(pushlex(\"]\"), commasep(typeexpr, \"]\", \",\"), poplex, afterType)\n if (type == \"{\") return cont(pushlex(\"}\"), typeprops, poplex, afterType)\n if (type == \"(\") return cont(commasep(typearg, \")\"), maybeReturnType, afterType)\n if (type == \"<\") return cont(commasep(typeexpr, \">\"), typeexpr)\n if (type == \"quasi\") return pass(quasiType, afterType)\n }\n function maybeReturnType(type) {\n if (type == \"=>\") return cont(typeexpr)\n }\n function typeprops(type) {\n if (type.match(/[\\}\\)\\]]/)) return cont()\n if (type == \",\" || type == \";\") return cont(typeprops)\n return pass(typeprop, typeprops)\n }\n function typeprop(type, value) {\n if (type == \"variable\" || cx.style == \"keyword\") {\n cx.marked = \"property\"\n return cont(typeprop)\n } else if (value == \"?\" || type == \"number\" || type == \"string\") {\n return cont(typeprop)\n } else if (type == \":\") {\n return cont(typeexpr)\n } else if (type == \"[\") {\n return cont(expect(\"variable\"), maybetypeOrIn, expect(\"]\"), typeprop)\n } else if (type == \"(\") {\n return pass(functiondecl, typeprop)\n } else if (!type.match(/[;\\}\\)\\],]/)) {\n return cont()\n }\n }\n function quasiType(type, value) {\n if (type != \"quasi\") return pass();\n if (value.slice(value.length - 2) != \"${\") return cont(quasiType);\n return cont(typeexpr, continueQuasiType);\n }\n function continueQuasiType(type) {\n if (type == \"}\") {\n cx.marked = \"string.special\";\n cx.state.tokenize = tokenQuasi;\n return cont(quasiType);\n }\n }\n function typearg(type, value) {\n if (type == \"variable\" && cx.stream.match(/^\\s*[?:]/, false) || value == \"?\") return cont(typearg)\n if (type == \":\") return cont(typeexpr)\n if (type == \"spread\") return cont(typearg)\n return pass(typeexpr)\n }\n function afterType(type, value) {\n if (value == \"<\") return cont(pushlex(\">\"), commasep(typeexpr, \">\"), poplex, afterType)\n if (value == \"|\" || type == \".\" || value == \"&\") return cont(typeexpr)\n if (type == \"[\") return cont(typeexpr, expect(\"]\"), afterType)\n if (value == \"extends\" || value == \"implements\") { cx.marked = \"keyword\"; return cont(typeexpr) }\n if (value == \"?\") return cont(typeexpr, expect(\":\"), typeexpr)\n }\n function maybeTypeArgs(_, value) {\n if (value == \"<\") return cont(pushlex(\">\"), commasep(typeexpr, \">\"), poplex, afterType)\n }\n function typeparam() {\n return pass(typeexpr, maybeTypeDefault)\n }\n function maybeTypeDefault(_, value) {\n if (value == \"=\") return cont(typeexpr)\n }\n function vardef(_, value) {\n if (value == \"enum\") {cx.marked = \"keyword\"; return cont(enumdef)}\n return pass(pattern, maybetype, maybeAssign, vardefCont);\n }\n function pattern(type, value) {\n if (isTS && isModifier(value)) { cx.marked = \"keyword\"; return cont(pattern) }\n if (type == \"variable\") { register(value); return cont(); }\n if (type == \"spread\") return cont(pattern);\n if (type == \"[\") return contCommasep(eltpattern, \"]\");\n if (type == \"{\") return contCommasep(proppattern, \"}\");\n }\n function proppattern(type, value) {\n if (type == \"variable\" && !cx.stream.match(/^\\s*:/, false)) {\n register(value);\n return cont(maybeAssign);\n }\n if (type == \"variable\") cx.marked = \"property\";\n if (type == \"spread\") return cont(pattern);\n if (type == \"}\") return pass();\n if (type == \"[\") return cont(expression, expect(']'), expect(':'), proppattern);\n return cont(expect(\":\"), pattern, maybeAssign);\n }\n function eltpattern() {\n return pass(pattern, maybeAssign)\n }\n function maybeAssign(_type, value) {\n if (value == \"=\") return cont(expressionNoComma);\n }\n function vardefCont(type) {\n if (type == \",\") return cont(vardef);\n }\n function maybeelse(type, value) {\n if (type == \"keyword b\" && value == \"else\") return cont(pushlex(\"form\", \"else\"), statement, poplex);\n }\n function forspec(type, value) {\n if (value == \"await\") return cont(forspec);\n if (type == \"(\") return cont(pushlex(\")\"), forspec1, poplex);\n }\n function forspec1(type) {\n if (type == \"var\") return cont(vardef, forspec2);\n if (type == \"variable\") return cont(forspec2);\n return pass(forspec2)\n }\n function forspec2(type, value) {\n if (type == \")\") return cont()\n if (type == \";\") return cont(forspec2)\n if (value == \"in\" || value == \"of\") { cx.marked = \"keyword\"; return cont(expression, forspec2) }\n return pass(expression, forspec2)\n }\n function functiondef(type, value) {\n if (value == \"*\") {cx.marked = \"keyword\"; return cont(functiondef);}\n if (type == \"variable\") {register(value); return cont(functiondef);}\n if (type == \"(\") return cont(pushcontext, pushlex(\")\"), commasep(funarg, \")\"), poplex, mayberettype, statement, popcontext);\n if (isTS && value == \"<\") return cont(pushlex(\">\"), commasep(typeparam, \">\"), poplex, functiondef)\n }\n function functiondecl(type, value) {\n if (value == \"*\") {cx.marked = \"keyword\"; return cont(functiondecl);}\n if (type == \"variable\") {register(value); return cont(functiondecl);}\n if (type == \"(\") return cont(pushcontext, pushlex(\")\"), commasep(funarg, \")\"), poplex, mayberettype, popcontext);\n if (isTS && value == \"<\") return cont(pushlex(\">\"), commasep(typeparam, \">\"), poplex, functiondecl)\n }\n function typename(type, value) {\n if (type == \"keyword\" || type == \"variable\") {\n cx.marked = \"type\"\n return cont(typename)\n } else if (value == \"<\") {\n return cont(pushlex(\">\"), commasep(typeparam, \">\"), poplex)\n }\n }\n function funarg(type, value) {\n if (value == \"@\") cont(expression, funarg)\n if (type == \"spread\") return cont(funarg);\n if (isTS && isModifier(value)) { cx.marked = \"keyword\"; return cont(funarg); }\n if (isTS && type == \"this\") return cont(maybetype, maybeAssign)\n return pass(pattern, maybetype, maybeAssign);\n }\n function classExpression(type, value) {\n // Class expressions may have an optional name.\n if (type == \"variable\") return className(type, value);\n return classNameAfter(type, value);\n }\n function className(type, value) {\n if (type == \"variable\") {register(value); return cont(classNameAfter);}\n }\n function classNameAfter(type, value) {\n if (value == \"<\") return cont(pushlex(\">\"), commasep(typeparam, \">\"), poplex, classNameAfter)\n if (value == \"extends\" || value == \"implements\" || (isTS && type == \",\")) {\n if (value == \"implements\") cx.marked = \"keyword\";\n return cont(isTS ? typeexpr : expression, classNameAfter);\n }\n if (type == \"{\") return cont(pushlex(\"}\"), classBody, poplex);\n }\n function classBody(type, value) {\n if (type == \"async\" ||\n (type == \"variable\" &&\n (value == \"static\" || value == \"get\" || value == \"set\" || (isTS && isModifier(value))) &&\n cx.stream.match(/^\\s+#?[\\w$\\xa1-\\uffff]/, false))) {\n cx.marked = \"keyword\";\n return cont(classBody);\n }\n if (type == \"variable\" || cx.style == \"keyword\") {\n cx.marked = \"property\";\n return cont(classfield, classBody);\n }\n if (type == \"number\" || type == \"string\") return cont(classfield, classBody);\n if (type == \"[\")\n return cont(expression, maybetype, expect(\"]\"), classfield, classBody)\n if (value == \"*\") {\n cx.marked = \"keyword\";\n return cont(classBody);\n }\n if (isTS && type == \"(\") return pass(functiondecl, classBody)\n if (type == \";\" || type == \",\") return cont(classBody);\n if (type == \"}\") return cont();\n if (value == \"@\") return cont(expression, classBody)\n }\n function classfield(type, value) {\n if (value == \"!\" || value == \"?\") return cont(classfield)\n if (type == \":\") return cont(typeexpr, maybeAssign)\n if (value == \"=\") return cont(expressionNoComma)\n var context = cx.state.lexical.prev, isInterface = context && context.info == \"interface\"\n return pass(isInterface ? functiondecl : functiondef)\n }\n function afterExport(type, value) {\n if (value == \"*\") { cx.marked = \"keyword\"; return cont(maybeFrom, expect(\";\")); }\n if (value == \"default\") { cx.marked = \"keyword\"; return cont(expression, expect(\";\")); }\n if (type == \"{\") return cont(commasep(exportField, \"}\"), maybeFrom, expect(\";\"));\n return pass(statement);\n }\n function exportField(type, value) {\n if (value == \"as\") { cx.marked = \"keyword\"; return cont(expect(\"variable\")); }\n if (type == \"variable\") return pass(expressionNoComma, exportField);\n }\n function afterImport(type) {\n if (type == \"string\") return cont();\n if (type == \"(\") return pass(expression);\n if (type == \".\") return pass(maybeoperatorComma);\n return pass(importSpec, maybeMoreImports, maybeFrom);\n }\n function importSpec(type, value) {\n if (type == \"{\") return contCommasep(importSpec, \"}\");\n if (type == \"variable\") register(value);\n if (value == \"*\") cx.marked = \"keyword\";\n return cont(maybeAs);\n }\n function maybeMoreImports(type) {\n if (type == \",\") return cont(importSpec, maybeMoreImports)\n }\n function maybeAs(_type, value) {\n if (value == \"as\") { cx.marked = \"keyword\"; return cont(importSpec); }\n }\n function maybeFrom(_type, value) {\n if (value == \"from\") { cx.marked = \"keyword\"; return cont(expression); }\n }\n function arrayLiteral(type) {\n if (type == \"]\") return cont();\n return pass(commasep(expressionNoComma, \"]\"));\n }\n function enumdef() {\n return pass(pushlex(\"form\"), pattern, expect(\"{\"), pushlex(\"}\"), commasep(enummember, \"}\"), poplex, poplex)\n }\n function enummember() {\n return pass(pattern, maybeAssign);\n }\n\n function isContinuedStatement(state, textAfter) {\n return state.lastType == \"operator\" || state.lastType == \",\" ||\n isOperatorChar.test(textAfter.charAt(0)) ||\n /[,.]/.test(textAfter.charAt(0));\n }\n\n function expressionAllowed(stream, state, backUp) {\n return state.tokenize == tokenBase &&\n /^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\\[{}\\(,;:]|=>)$/.test(state.lastType) ||\n (state.lastType == \"quasi\" && /\\{\\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))\n }\n\n // Interface\n\n return {\n name: parserConfig.name,\n\n startState: function(indentUnit) {\n var state = {\n tokenize: tokenBase,\n lastType: \"sof\",\n cc: [],\n lexical: new JSLexical(-indentUnit, 0, \"block\", false),\n localVars: parserConfig.localVars,\n context: parserConfig.localVars && new Context(null, null, false),\n indented: 0\n };\n if (parserConfig.globalVars && typeof parserConfig.globalVars == \"object\")\n state.globalVars = parserConfig.globalVars;\n return state;\n },\n\n token: function(stream, state) {\n if (stream.sol()) {\n if (!state.lexical.hasOwnProperty(\"align\"))\n state.lexical.align = false;\n state.indented = stream.indentation();\n findFatArrow(stream, state);\n }\n if (state.tokenize != tokenComment && stream.eatSpace()) return null;\n var style = state.tokenize(stream, state);\n if (type == \"comment\") return style;\n state.lastType = type == \"operator\" && (content == \"++\" || content == \"--\") ? \"incdec\" : type;\n return parseJS(state, style, type, content, stream);\n },\n\n indent: function(state, textAfter, cx) {\n if (state.tokenize == tokenComment || state.tokenize == tokenQuasi) return null;\n if (state.tokenize != tokenBase) return 0;\n var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top\n // Kludge to prevent 'maybelse' from blocking lexical scope pops\n if (!/^\\s*else\\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {\n var c = state.cc[i];\n if (c == poplex) lexical = lexical.prev;\n else if (c != maybeelse && c != popcontext) break;\n }\n while ((lexical.type == \"stat\" || lexical.type == \"form\") &&\n (firstChar == \"}\" || ((top = state.cc[state.cc.length - 1]) &&\n (top == maybeoperatorComma || top == maybeoperatorNoComma) &&\n !/^[,\\.=+\\-*:?[\\(]/.test(textAfter))))\n lexical = lexical.prev;\n if (statementIndent && lexical.type == \")\" && lexical.prev.type == \"stat\")\n lexical = lexical.prev;\n var type = lexical.type, closing = firstChar == type;\n\n if (type == \"vardef\") return lexical.indented + (state.lastType == \"operator\" || state.lastType == \",\" ? lexical.info.length + 1 : 0);\n else if (type == \"form\" && firstChar == \"{\") return lexical.indented;\n else if (type == \"form\") return lexical.indented + cx.unit;\n else if (type == \"stat\")\n return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || cx.unit : 0);\n else if (lexical.info == \"switch\" && !closing && parserConfig.doubleIndentSwitch != false)\n return lexical.indented + (/^(?:case|default)\\b/.test(textAfter) ? cx.unit : 2 * cx.unit);\n else if (lexical.align) return lexical.column + (closing ? 0 : 1);\n else return lexical.indented + (closing ? 0 : cx.unit);\n },\n\n languageData: {\n indentOnInput: /^\\s*(?:case .*?:|default:|\\{|\\})$/,\n commentTokens: jsonMode ? undefined : {line: \"//\", block: {open: \"/*\", close: \"*/\"}},\n closeBrackets: {brackets: [\"(\", \"[\", \"{\", \"'\", '\"', \"`\"]},\n wordChars: \"$\"\n }\n };\n};\n\nexport const javascript = mkJavaScript({name: \"javascript\"})\nexport const json = mkJavaScript({name: \"json\", json: true})\nexport const jsonld = mkJavaScript({name: \"json\", jsonld: true})\nexport const typescript = mkJavaScript({name: \"typescript\", typescript: true})\n"],"names":["mkJavaScript","parserConfig","type","content","statementIndent","jsonldMode","jsonld","jsonMode","json","isTS","typescript","wordRE","wordCharacters","keywords","kw","style","A","B","C","D","operator","atom","isOperatorChar","isJsonldKeyword","ret","tp","cont","tokenBase","stream","state","quote","ch","next","tokenize","escaped","peek","match","test","eat","tokenComment","skipToEnd","backUp","lastType","string","slice","pos","expressionAllowed","inSet","readRegexp","current","tokenQuasi","eatWhile","start","lexical","word","propertyIsEnumerable","maybeEnd","brackets","findFatArrow","fatArrowAt","arrow","indexOf","m","exec","index","depth","sawSomething","charAt","bracket","atomicTypes","JSLexical","indented","column","align","prev","info","this","inScope","varname","v","localVars","name","cx","context","vars","marked","cc","pass","i","arguments","length","push","apply","inList","list","register","block","newContext","registerVarScoped","Var","globalVars","inner","Context","isModifier","defaultVars","pushcontext","pushblockcontext","popcontext","pushlex","result","indent","outer","lex","poplex","expect","wanted","exp","statement","value","vardef","parenExpr","maybeexpression","pop","maybeelse","functiondef","forspec","className","enumdef","typename","typeexpr","pattern","expression","maybelabel","maybeCatchBinding","afterExport","afterImport","funarg","expressionInner","expressionNoComma","noComma","body","arrowBodyNoComma","arrowBody","commasep","maybeop","maybeoperatorNoComma","maybeoperatorComma","hasOwnProperty","classExpression","arrayLiteral","contCommasep","objprop","quasi","targetNoComma","target","maybeTypeArgs","maybeTarget","me","expr","property","continueQuasi","_","getterSetter","afterprop","maybetype","what","end","sep","proceed","maybetypeOrIn","mayberettype","isKW","afterType","typeprops","typearg","maybeReturnType","quasiType","typeprop","functiondecl","continueQuasiType","typeparam","maybeTypeDefault","maybeAssign","vardefCont","eltpattern","proppattern","_type","forspec1","forspec2","classNameAfter","classBody","classfield","maybeFrom","exportField","importSpec","maybeMoreImports","maybeAs","enummember","startState","indentUnit","token","sol","indentation","eatSpace","parseJS","textAfter","top","firstChar","c","closing","unit","isContinuedStatement","doubleIndentSwitch","languageData","indentOnInput","commentTokens","undefined","line","open","close","closeBrackets","wordChars","javascript"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/386.index.js b/book/_build/html/_static/386.index.js
new file mode 100644
index 0000000..a097d58
--- /dev/null
+++ b/book/_build/html/_static/386.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[386],{386:(t,e,n)=>{n.r(e),n.d(e,{commonLisp:()=>d});var r,o=/^(block|let*|return-from|catch|load-time-value|setq|eval-when|locally|symbol-macrolet|flet|macrolet|tagbody|function|multiple-value-call|the|go|multiple-value-prog1|throw|if|progn|unwind-protect|labels|progv|let|quote)$/,a=/^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/,l=/^(?:[+\-]?(?:\d+|\d*\.\d+)(?:[efd][+\-]?\d+)?|[+\-]?\d+(?:\/[+\-]?\d+)?|#b[+\-]?[01]+|#o[+\-]?[0-7]+|#x[+\-]?[\da-f]+)/,c=/[^\s'`,@()\[\]";]/;function i(t){for(var e;e=t.next();)if("\\"==e)t.next();else if(!c.test(e)){t.backUp(1);break}return t.current()}function u(t,e){if(t.eatSpace())return r="ws",null;if(t.match(l))return"number";var n;if("\\"==(n=t.next())&&(n=t.next()),'"'==n)return(e.tokenize=s)(t,e);if("("==n)return r="open","bracket";if(")"==n||"]"==n)return r="close","bracket";if(";"==n)return t.skipToEnd(),r="ws","comment";if(/['`,@]/.test(n))return null;if("|"==n)return t.skipTo("|")?(t.next(),"variableName"):(t.skipToEnd(),"error");if("#"==n)return"("==(n=t.next())?(r="open","bracket"):/[+\-=\.']/.test(n)||/\d/.test(n)&&t.match(/^\d*#/)?null:"|"==n?(e.tokenize=f)(t,e):":"==n?(i(t),"meta"):"\\"==n?(t.next(),i(t),"string.special"):"error";var c=i(t);return"."==c?null:(r="symbol","nil"==c||"t"==c||":"==c.charAt(0)?"atom":"open"==e.lastType&&(o.test(c)||a.test(c))?"keyword":"&"==c.charAt(0)?"variableName.special":"variableName")}function s(t,e){for(var n,r=!1;n=t.next();){if('"'==n&&!r){e.tokenize=u;break}r=!r&&"\\"==n}return"string"}function f(t,e){for(var n,o;n=t.next();){if("#"==n&&"|"==o){e.tokenize=u;break}o=n}return r="ws","comment"}const d={name:"commonlisp",startState:function(){return{ctx:{prev:null,start:0,indentTo:0},lastType:null,tokenize:u}},token:function(t,e){t.sol()&&"number"!=typeof e.ctx.indentTo&&(e.ctx.indentTo=e.ctx.start+1),r=null;var n=e.tokenize(t,e);return"ws"!=r&&(null==e.ctx.indentTo?"symbol"==r&&a.test(t.current())?e.ctx.indentTo=e.ctx.start+t.indentUnit:e.ctx.indentTo="next":"next"==e.ctx.indentTo&&(e.ctx.indentTo=t.column()),e.lastType=r),"open"==r?e.ctx={prev:e.ctx,start:t.column(),indentTo:null}:"close"==r&&(e.ctx=e.ctx.prev||e.ctx),n},indent:function(t){var e=t.ctx.indentTo;return"number"==typeof e?e:t.ctx.start+1},languageData:{commentTokens:{line:";;",block:{open:"#|",close:"|#"}},closeBrackets:{brackets:["(","[","{",'"']}}}}}]);
+//# sourceMappingURL=386.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/386.index.js.map b/book/_build/html/_static/386.index.js.map
new file mode 100644
index 0000000..484dd28
--- /dev/null
+++ b/book/_build/html/_static/386.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"386.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/commonlisp.js"],"sourcesContent":["var specialForm = /^(block|let*|return-from|catch|load-time-value|setq|eval-when|locally|symbol-macrolet|flet|macrolet|tagbody|function|multiple-value-call|the|go|multiple-value-prog1|throw|if|progn|unwind-protect|labels|progv|let|quote)$/;\nvar assumeBody = /^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/;\nvar numLiteral = /^(?:[+\\-]?(?:\\d+|\\d*\\.\\d+)(?:[efd][+\\-]?\\d+)?|[+\\-]?\\d+(?:\\/[+\\-]?\\d+)?|#b[+\\-]?[01]+|#o[+\\-]?[0-7]+|#x[+\\-]?[\\da-f]+)/;\nvar symbol = /[^\\s'`,@()\\[\\]\";]/;\nvar type;\n\nfunction readSym(stream) {\n var ch;\n while (ch = stream.next()) {\n if (ch == \"\\\\\") stream.next();\n else if (!symbol.test(ch)) { stream.backUp(1); break; }\n }\n return stream.current();\n}\n\nfunction base(stream, state) {\n if (stream.eatSpace()) {type = \"ws\"; return null;}\n if (stream.match(numLiteral)) return \"number\";\n var ch = stream.next();\n if (ch == \"\\\\\") ch = stream.next();\n\n if (ch == '\"') return (state.tokenize = inString)(stream, state);\n else if (ch == \"(\") { type = \"open\"; return \"bracket\"; }\n else if (ch == \")\" || ch == \"]\") { type = \"close\"; return \"bracket\"; }\n else if (ch == \";\") { stream.skipToEnd(); type = \"ws\"; return \"comment\"; }\n else if (/['`,@]/.test(ch)) return null;\n else if (ch == \"|\") {\n if (stream.skipTo(\"|\")) { stream.next(); return \"variableName\"; }\n else { stream.skipToEnd(); return \"error\"; }\n } else if (ch == \"#\") {\n var ch = stream.next();\n if (ch == \"(\") { type = \"open\"; return \"bracket\"; }\n else if (/[+\\-=\\.']/.test(ch)) return null;\n else if (/\\d/.test(ch) && stream.match(/^\\d*#/)) return null;\n else if (ch == \"|\") return (state.tokenize = inComment)(stream, state);\n else if (ch == \":\") { readSym(stream); return \"meta\"; }\n else if (ch == \"\\\\\") { stream.next(); readSym(stream); return \"string.special\" }\n else return \"error\";\n } else {\n var name = readSym(stream);\n if (name == \".\") return null;\n type = \"symbol\";\n if (name == \"nil\" || name == \"t\" || name.charAt(0) == \":\") return \"atom\";\n if (state.lastType == \"open\" && (specialForm.test(name) || assumeBody.test(name))) return \"keyword\";\n if (name.charAt(0) == \"&\") return \"variableName.special\";\n return \"variableName\";\n }\n}\n\nfunction inString(stream, state) {\n var escaped = false, next;\n while (next = stream.next()) {\n if (next == '\"' && !escaped) { state.tokenize = base; break; }\n escaped = !escaped && next == \"\\\\\";\n }\n return \"string\";\n}\n\nfunction inComment(stream, state) {\n var next, last;\n while (next = stream.next()) {\n if (next == \"#\" && last == \"|\") { state.tokenize = base; break; }\n last = next;\n }\n type = \"ws\";\n return \"comment\";\n}\n\nexport const commonLisp = {\n name: \"commonlisp\",\n startState: function () {\n return {ctx: {prev: null, start: 0, indentTo: 0}, lastType: null, tokenize: base};\n },\n\n token: function (stream, state) {\n if (stream.sol() && typeof state.ctx.indentTo != \"number\")\n state.ctx.indentTo = state.ctx.start + 1;\n\n type = null;\n var style = state.tokenize(stream, state);\n if (type != \"ws\") {\n if (state.ctx.indentTo == null) {\n if (type == \"symbol\" && assumeBody.test(stream.current()))\n state.ctx.indentTo = state.ctx.start + stream.indentUnit;\n else\n state.ctx.indentTo = \"next\";\n } else if (state.ctx.indentTo == \"next\") {\n state.ctx.indentTo = stream.column();\n }\n state.lastType = type;\n }\n if (type == \"open\") state.ctx = {prev: state.ctx, start: stream.column(), indentTo: null};\n else if (type == \"close\") state.ctx = state.ctx.prev || state.ctx;\n return style;\n },\n\n indent: function (state) {\n var i = state.ctx.indentTo;\n return typeof i == \"number\" ? i : state.ctx.start + 1;\n },\n\n languageData: {\n commentTokens: {line: \";;\", block: {open: \"#|\", close: \"|#\"}},\n closeBrackets: {brackets: [\"(\", \"[\", \"{\", '\"']}\n }\n};\n\n"],"names":["type","specialForm","assumeBody","numLiteral","symbol","readSym","stream","ch","next","test","backUp","current","base","state","eatSpace","match","tokenize","inString","skipToEnd","skipTo","inComment","name","charAt","lastType","escaped","last","commonLisp","startState","ctx","prev","start","indentTo","token","sol","style","indentUnit","column","indent","i","languageData","commentTokens","line","block","open","close","closeBrackets","brackets"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/4127.index.js b/book/_build/html/_static/4127.index.js
new file mode 100644
index 0000000..5c38cc4
--- /dev/null
+++ b/book/_build/html/_static/4127.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[4127],{14127:(e,n,t)=>{function r(e){return new RegExp("^(("+e.join(")|(")+"))\\b")}t.r(n),t.d(n,{octave:()=>k});var i=new RegExp("^[\\+\\-\\*/&|\\^~<>!@'\\\\]"),a=new RegExp("^[\\(\\[\\{\\},:=;\\.]"),o=new RegExp("^((==)|(~=)|(<=)|(>=)|(<<)|(>>)|(\\.[\\+\\-\\*/\\^\\\\]))"),c=new RegExp("^((!=)|(\\+=)|(\\-=)|(\\*=)|(/=)|(&=)|(\\|=)|(\\^=))"),m=new RegExp("^((>>=)|(<<=))"),s=new RegExp("^[\\]\\)]"),u=new RegExp("^[_A-Za-z¡-][_A-Za-z0-9¡-]*"),l=r(["error","eval","function","abs","acos","atan","asin","cos","cosh","exp","log","prod","sum","log10","max","min","sign","sin","sinh","sqrt","tan","reshape","break","zeros","default","margin","round","ones","rand","syn","ceil","floor","size","clear","zeros","eye","mean","std","cov","det","eig","inv","norm","rank","trace","expm","logm","sqrtm","linspace","plot","title","xlabel","ylabel","legend","text","grid","meshgrid","mesh","num2str","fft","ifft","arrayfun","cellfun","input","fliplr","flipud","ismember"]),f=r(["return","case","switch","else","elseif","end","endif","endfunction","if","otherwise","do","for","while","try","catch","classdef","properties","events","methods","global","persistent","endfor","endwhile","printf","sprintf","disp","until","continue","pkg"]);function h(e,n){return e.sol()||"'"!==e.peek()?(n.tokenize=d,d(e,n)):(e.next(),n.tokenize=d,"operator")}function p(e,n){return e.match(/^.*%}/)?(n.tokenize=d,"comment"):(e.skipToEnd(),"comment")}function d(e,n){if(e.eatSpace())return null;if(e.match("%{"))return n.tokenize=p,e.skipToEnd(),"comment";if(e.match(/^[%#]/))return e.skipToEnd(),"comment";if(e.match(/^[0-9\.+-]/,!1)){if(e.match(/^[+-]?0x[0-9a-fA-F]+[ij]?/))return e.tokenize=d,"number";if(e.match(/^[+-]?\d*\.\d+([EeDd][+-]?\d+)?[ij]?/))return"number";if(e.match(/^[+-]?\d+([EeDd][+-]?\d+)?[ij]?/))return"number"}if(e.match(r(["nan","NaN","inf","Inf"])))return"number";var t=e.match(/^"(?:[^"]|"")*("|$)/)||e.match(/^'(?:[^']|'')*('|$)/);return t?t[1]?"string":"error":e.match(f)?"keyword":e.match(l)?"builtin":e.match(u)?"variable":e.match(i)||e.match(o)?"operator":e.match(a)||e.match(c)||e.match(m)?null:e.match(s)?(n.tokenize=h,null):(e.next(),"error")}const k={name:"octave",startState:function(){return{tokenize:d}},token:function(e,n){var t=n.tokenize(e,n);return"number"!==t&&"variable"!==t||(n.tokenize=h),t},languageData:{commentTokens:{line:"%"}}}}}]);
+//# sourceMappingURL=4127.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/4127.index.js.map b/book/_build/html/_static/4127.index.js.map
new file mode 100644
index 0000000..170f681
--- /dev/null
+++ b/book/_build/html/_static/4127.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"4127.index.js","mappings":"+FAAA,SAASA,EAAWC,GAClB,OAAO,IAAIC,OAAO,MAAQD,EAAME,KAAK,OAAS,QAChD,C,6BAEA,IAAIC,EAAkB,IAAIF,OAAO,gCAC7BG,EAAmB,IAAIH,OAAO,0BAC9BI,EAAkB,IAAIJ,OAAO,6DAC7BK,EAAmB,IAAIL,OAAO,wDAC9BM,EAAmB,IAAIN,OAAO,kBAC9BO,EAAgB,IAAIP,OAAO,aAC3BQ,EAAc,IAAIR,OAAO,iCAEzBS,EAAWX,EAAW,CACxB,QAAS,OAAQ,WAAY,MAAO,OAAQ,OAAQ,OAAQ,MAC5D,OAAQ,MAAO,MAAO,OAAQ,MAAO,QAAS,MAAO,MAAO,OAAQ,MAAO,OAC3E,OAAQ,MAAO,UAAW,QAAS,QAAS,UAAW,SAAU,QAAS,OAC1E,OAAQ,MAAO,OAAQ,QAAS,OAAQ,QAAS,QAAS,MAAO,OAAQ,MAAO,MAChF,MAAO,MAAO,MAAO,OAAQ,OAAQ,QAAS,OAAQ,OAAQ,QAAS,WAAY,OACnF,QAAS,SAAU,SAAU,SAAU,OAAQ,OAAQ,WAAY,OAAQ,UAC3E,MAAO,OAAQ,WAAY,UAAW,QAAS,SAAU,SAAU,aAGjEY,EAAWZ,EAAW,CACxB,SAAU,OAAQ,SAAU,OAAQ,SAAU,MAAO,QAAS,cAC9D,KAAM,YAAa,KAAM,MAAO,QAAS,MAAO,QAAS,WAAY,aAAc,SACnF,UAAW,SAAU,aAAc,SAAU,WAAY,SAAU,UAAW,OAAQ,QACtF,WAAY,QAKd,SAASa,EAAeC,EAAQC,GAC9B,OAAKD,EAAOE,OAA2B,MAAlBF,EAAOG,QAK5BF,EAAMG,SAAWC,EACVA,EAAUL,EAAQC,KALvBD,EAAOM,OACPL,EAAMG,SAAWC,EACV,WAIX,CAGA,SAASE,EAAaP,EAAQC,GAC5B,OAAID,EAAOQ,MAAM,UACfP,EAAMG,SAAWC,EACV,YAETL,EAAOS,YACA,UACT,CAEA,SAASJ,EAAUL,EAAQC,GAEzB,GAAID,EAAOU,WAAY,OAAO,KAG9B,GAAIV,EAAOQ,MAAM,MAGf,OAFAP,EAAMG,SAAWG,EACjBP,EAAOS,YACA,UAGT,GAAIT,EAAOQ,MAAM,SAEf,OADAR,EAAOS,YACA,UAIT,GAAIT,EAAOQ,MAAM,cAAc,GAAQ,CACrC,GAAIR,EAAOQ,MAAM,6BAEf,OADAR,EAAOI,SAAWC,EACX,SACT,GAAIL,EAAOQ,MAAM,wCAA2C,MAAO,SACnE,GAAIR,EAAOQ,MAAM,mCAAsC,MAAO,QAChE,CACA,GAAIR,EAAOQ,MAAMtB,EAAW,CAAC,MAAM,MAAM,MAAM,SAAY,MAAO,SAGlE,IAAIyB,EAAIX,EAAOQ,MAAM,wBAA0BR,EAAOQ,MAAM,uBAC5D,OAAIG,EAAYA,EAAE,GAAK,SAAW,QAG9BX,EAAOQ,MAAMV,GAAoB,UACjCE,EAAOQ,MAAMX,GAAoB,UACjCG,EAAOQ,MAAMZ,GAAuB,WAEpCI,EAAOQ,MAAMlB,IAAoBU,EAAOQ,MAAMhB,GAA2B,WACzEQ,EAAOQ,MAAMjB,IAAqBS,EAAOQ,MAAMf,IAAqBO,EAAOQ,MAAMd,GAA4B,KAE7GM,EAAOQ,MAAMb,IACfM,EAAMG,SAAWL,EACV,OAKTC,EAAOM,OACA,QACT,CAGO,MAAMM,EAAS,CACpBC,KAAM,SAENC,WAAY,WACV,MAAO,CACLV,SAAUC,EAEd,EAEAU,MAAO,SAASf,EAAQC,GACtB,IAAIe,EAAQf,EAAMG,SAASJ,EAAQC,GAInC,MAHc,WAAVe,GAAgC,aAAVA,IACxBf,EAAMG,SAAWL,GAEZiB,CACT,EAEAC,aAAc,CACZC,cAAe,CAACC,KAAM,M","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/octave.js"],"sourcesContent":["function wordRegexp(words) {\n return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\");\n}\n\nvar singleOperators = new RegExp(\"^[\\\\+\\\\-\\\\*/&|\\\\^~<>!@'\\\\\\\\]\");\nvar singleDelimiters = new RegExp('^[\\\\(\\\\[\\\\{\\\\},:=;\\\\.]');\nvar doubleOperators = new RegExp(\"^((==)|(~=)|(<=)|(>=)|(<<)|(>>)|(\\\\.[\\\\+\\\\-\\\\*/\\\\^\\\\\\\\]))\");\nvar doubleDelimiters = new RegExp(\"^((!=)|(\\\\+=)|(\\\\-=)|(\\\\*=)|(/=)|(&=)|(\\\\|=)|(\\\\^=))\");\nvar tripleDelimiters = new RegExp(\"^((>>=)|(<<=))\");\nvar expressionEnd = new RegExp(\"^[\\\\]\\\\)]\");\nvar identifiers = new RegExp(\"^[_A-Za-z\\xa1-\\uffff][_A-Za-z0-9\\xa1-\\uffff]*\");\n\nvar builtins = wordRegexp([\n 'error', 'eval', 'function', 'abs', 'acos', 'atan', 'asin', 'cos',\n 'cosh', 'exp', 'log', 'prod', 'sum', 'log10', 'max', 'min', 'sign', 'sin', 'sinh',\n 'sqrt', 'tan', 'reshape', 'break', 'zeros', 'default', 'margin', 'round', 'ones',\n 'rand', 'syn', 'ceil', 'floor', 'size', 'clear', 'zeros', 'eye', 'mean', 'std', 'cov',\n 'det', 'eig', 'inv', 'norm', 'rank', 'trace', 'expm', 'logm', 'sqrtm', 'linspace', 'plot',\n 'title', 'xlabel', 'ylabel', 'legend', 'text', 'grid', 'meshgrid', 'mesh', 'num2str',\n 'fft', 'ifft', 'arrayfun', 'cellfun', 'input', 'fliplr', 'flipud', 'ismember'\n]);\n\nvar keywords = wordRegexp([\n 'return', 'case', 'switch', 'else', 'elseif', 'end', 'endif', 'endfunction',\n 'if', 'otherwise', 'do', 'for', 'while', 'try', 'catch', 'classdef', 'properties', 'events',\n 'methods', 'global', 'persistent', 'endfor', 'endwhile', 'printf', 'sprintf', 'disp', 'until',\n 'continue', 'pkg'\n]);\n\n\n// tokenizers\nfunction tokenTranspose(stream, state) {\n if (!stream.sol() && stream.peek() === '\\'') {\n stream.next();\n state.tokenize = tokenBase;\n return 'operator';\n }\n state.tokenize = tokenBase;\n return tokenBase(stream, state);\n}\n\n\nfunction tokenComment(stream, state) {\n if (stream.match(/^.*%}/)) {\n state.tokenize = tokenBase;\n return 'comment';\n };\n stream.skipToEnd();\n return 'comment';\n}\n\nfunction tokenBase(stream, state) {\n // whitespaces\n if (stream.eatSpace()) return null;\n\n // Handle one line Comments\n if (stream.match('%{')){\n state.tokenize = tokenComment;\n stream.skipToEnd();\n return 'comment';\n }\n\n if (stream.match(/^[%#]/)){\n stream.skipToEnd();\n return 'comment';\n }\n\n // Handle Number Literals\n if (stream.match(/^[0-9\\.+-]/, false)) {\n if (stream.match(/^[+-]?0x[0-9a-fA-F]+[ij]?/)) {\n stream.tokenize = tokenBase;\n return 'number'; };\n if (stream.match(/^[+-]?\\d*\\.\\d+([EeDd][+-]?\\d+)?[ij]?/)) { return 'number'; };\n if (stream.match(/^[+-]?\\d+([EeDd][+-]?\\d+)?[ij]?/)) { return 'number'; };\n }\n if (stream.match(wordRegexp(['nan','NaN','inf','Inf']))) { return 'number'; };\n\n // Handle Strings\n var m = stream.match(/^\"(?:[^\"]|\"\")*(\"|$)/) || stream.match(/^'(?:[^']|'')*('|$)/)\n if (m) { return m[1] ? 'string' : \"error\"; }\n\n // Handle words\n if (stream.match(keywords)) { return 'keyword'; } ;\n if (stream.match(builtins)) { return 'builtin'; } ;\n if (stream.match(identifiers)) { return 'variable'; } ;\n\n if (stream.match(singleOperators) || stream.match(doubleOperators)) { return 'operator'; };\n if (stream.match(singleDelimiters) || stream.match(doubleDelimiters) || stream.match(tripleDelimiters)) { return null; };\n\n if (stream.match(expressionEnd)) {\n state.tokenize = tokenTranspose;\n return null;\n };\n\n\n // Handle non-detected items\n stream.next();\n return 'error';\n};\n\n\nexport const octave = {\n name: \"octave\",\n\n startState: function() {\n return {\n tokenize: tokenBase\n };\n },\n\n token: function(stream, state) {\n var style = state.tokenize(stream, state);\n if (style === 'number' || style === 'variable'){\n state.tokenize = tokenTranspose;\n }\n return style;\n },\n\n languageData: {\n commentTokens: {line: \"%\"}\n }\n};\n\n"],"names":["wordRegexp","words","RegExp","join","singleOperators","singleDelimiters","doubleOperators","doubleDelimiters","tripleDelimiters","expressionEnd","identifiers","builtins","keywords","tokenTranspose","stream","state","sol","peek","tokenize","tokenBase","next","tokenComment","match","skipToEnd","eatSpace","m","octave","name","startState","token","style","languageData","commentTokens","line"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/4140.index.js b/book/_build/html/_static/4140.index.js
new file mode 100644
index 0000000..c8a9b19
--- /dev/null
+++ b/book/_build/html/_static/4140.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[4140],{84140:(e,t,n)=>{n.r(t),n.d(t,{yacas:()=>k});var r=function(e){for(var t={},n="Assert BackQuote D Defun Deriv For ForEach FromFile FromString Function Integrate InverseTaylor Limit LocalSymbols Macro MacroRule MacroRulePattern NIntegrate Rule RulePattern Subst TD TExplicitSum TSum Taylor Taylor1 Taylor2 Taylor3 ToFile ToStdout ToString TraceRule Until While".split(" "),r=0;r|<|&|\||_|`|'|\^|\?|!|%|#)/,!0,!1)?"operator":"error"}function s(e,t){for(var n,r=!1,o=!1;null!=(n=e.next());){if('"'===n&&!o){r=!0;break}o=!o&&"\\"===n}return r&&!o&&(t.tokenize=l),"string"}function p(e,t){for(var n,r;null!=(r=e.next());){if("*"===n&&"/"===r){t.tokenize=l;break}n=r}return"comment"}function f(e){var t=null;return e.scopes.length>0&&(t=e.scopes[e.scopes.length-1]),t}const k={name:"yacas",startState:function(){return{tokenize:l,scopes:[]}},token:function(e,t){return e.eatSpace()?null:t.tokenize(e,t)},indent:function(e,t,n){if(e.tokenize!==l&&null!==e.tokenize)return null;var r=0;return"]"!==t&&"];"!==t&&"}"!==t&&"};"!==t&&");"!==t||(r=-1),(e.scopes.length+r)*n.unit},languageData:{electricInput:/[{}\[\]()\;]/,commentTokens:{line:"//",block:{open:"/*",close:"*/"}}}}}}]);
+//# sourceMappingURL=4140.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/4140.index.js.map b/book/_build/html/_static/4140.index.js.map
new file mode 100644
index 0000000..77a8178
--- /dev/null
+++ b/book/_build/html/_static/4140.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"4140.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/yacas.js"],"sourcesContent":["function words(str) {\n var obj = {}, words = str.split(\" \");\n for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n return obj;\n}\n\nvar bodiedOps = words(\"Assert BackQuote D Defun Deriv For ForEach FromFile \" +\n \"FromString Function Integrate InverseTaylor Limit \" +\n \"LocalSymbols Macro MacroRule MacroRulePattern \" +\n \"NIntegrate Rule RulePattern Subst TD TExplicitSum \" +\n \"TSum Taylor Taylor1 Taylor2 Taylor3 ToFile \" +\n \"ToStdout ToString TraceRule Until While\");\n\n// patterns\nvar pFloatForm = \"(?:(?:\\\\.\\\\d+|\\\\d+\\\\.\\\\d*|\\\\d+)(?:[eE][+-]?\\\\d+)?)\";\nvar pIdentifier = \"(?:[a-zA-Z\\\\$'][a-zA-Z0-9\\\\$']*)\";\n\n// regular expressions\nvar reFloatForm = new RegExp(pFloatForm);\nvar reIdentifier = new RegExp(pIdentifier);\nvar rePattern = new RegExp(pIdentifier + \"?_\" + pIdentifier);\nvar reFunctionLike = new RegExp(pIdentifier + \"\\\\s*\\\\(\");\n\nfunction tokenBase(stream, state) {\n var ch;\n\n // get next character\n ch = stream.next();\n\n // string\n if (ch === '\"') {\n state.tokenize = tokenString;\n return state.tokenize(stream, state);\n }\n\n // comment\n if (ch === '/') {\n if (stream.eat('*')) {\n state.tokenize = tokenComment;\n return state.tokenize(stream, state);\n }\n if (stream.eat(\"/\")) {\n stream.skipToEnd();\n return \"comment\";\n }\n }\n\n // go back one character\n stream.backUp(1);\n\n // update scope info\n var m = stream.match(/^(\\w+)\\s*\\(/, false);\n if (m !== null && bodiedOps.hasOwnProperty(m[1]))\n state.scopes.push('bodied');\n\n var scope = currentScope(state);\n\n if (scope === 'bodied' && ch === '[')\n state.scopes.pop();\n\n if (ch === '[' || ch === '{' || ch === '(')\n state.scopes.push(ch);\n\n scope = currentScope(state);\n\n if (scope === '[' && ch === ']' ||\n scope === '{' && ch === '}' ||\n scope === '(' && ch === ')')\n state.scopes.pop();\n\n if (ch === ';') {\n while (scope === 'bodied') {\n state.scopes.pop();\n scope = currentScope(state);\n }\n }\n\n // look for ordered rules\n if (stream.match(/\\d+ *#/, true, false)) {\n return 'qualifier';\n }\n\n // look for numbers\n if (stream.match(reFloatForm, true, false)) {\n return 'number';\n }\n\n // look for placeholders\n if (stream.match(rePattern, true, false)) {\n return 'variableName.special';\n }\n\n // match all braces separately\n if (stream.match(/(?:\\[|\\]|{|}|\\(|\\))/, true, false)) {\n return 'bracket';\n }\n\n // literals looking like function calls\n if (stream.match(reFunctionLike, true, false)) {\n stream.backUp(1);\n return 'variableName.function';\n }\n\n // all other identifiers\n if (stream.match(reIdentifier, true, false)) {\n return 'variable';\n }\n\n // operators; note that operators like @@ or /; are matched separately for each symbol.\n if (stream.match(/(?:\\\\|\\+|\\-|\\*|\\/|,|;|\\.|:|@|~|=|>|<|&|\\||_|`|'|\\^|\\?|!|%|#)/, true, false)) {\n return 'operator';\n }\n\n // everything else is an error\n return 'error';\n}\n\nfunction tokenString(stream, state) {\n var next, end = false, escaped = false;\n while ((next = stream.next()) != null) {\n if (next === '\"' && !escaped) {\n end = true;\n break;\n }\n escaped = !escaped && next === '\\\\';\n }\n if (end && !escaped) {\n state.tokenize = tokenBase;\n }\n return 'string';\n};\n\nfunction tokenComment(stream, state) {\n var prev, next;\n while((next = stream.next()) != null) {\n if (prev === '*' && next === '/') {\n state.tokenize = tokenBase;\n break;\n }\n prev = next;\n }\n return 'comment';\n}\n\nfunction currentScope(state) {\n var scope = null;\n if (state.scopes.length > 0)\n scope = state.scopes[state.scopes.length - 1];\n return scope;\n}\n\nexport const yacas = {\n name: \"yacas\",\n startState: function() {\n return {\n tokenize: tokenBase,\n scopes: []\n };\n },\n token: function(stream, state) {\n if (stream.eatSpace()) return null;\n return state.tokenize(stream, state);\n },\n indent: function(state, textAfter, cx) {\n if (state.tokenize !== tokenBase && state.tokenize !== null)\n return null;\n\n var delta = 0;\n if (textAfter === ']' || textAfter === '];' ||\n textAfter === '}' || textAfter === '};' ||\n textAfter === ');')\n delta = -1;\n\n return (state.scopes.length + delta) * cx.unit;\n },\n\n languageData: {\n electricInput: /[{}\\[\\]()\\;]/,\n commentTokens: {line: \"//\", block: {open: \"/*\", close: \"*/\"}}\n }\n};\n"],"names":["bodiedOps","str","obj","words","split","i","length","pIdentifier","reFloatForm","RegExp","reIdentifier","rePattern","reFunctionLike","tokenBase","stream","state","ch","next","tokenize","tokenString","eat","tokenComment","skipToEnd","backUp","m","match","hasOwnProperty","scopes","push","scope","currentScope","pop","end","escaped","prev","yacas","name","startState","token","eatSpace","indent","textAfter","cx","delta","unit","languageData","electricInput","commentTokens","line","block","open","close"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/4211.index.js b/book/_build/html/_static/4211.index.js
new file mode 100644
index 0000000..8b2eebe
--- /dev/null
+++ b/book/_build/html/_static/4211.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[4211],{4211:(e,O,a)=>{a.r(O),a.d(O,{css:()=>x,cssCompletionSource:()=>W,cssLanguage:()=>X,defineCSSCompletionSource:()=>R});var t=a(51392),o=a(86253);const r=[9,10,11,12,13,32,133,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8232,8233,8239,8287,12288];function l(e){return e>=65&&e<=90||e>=97&&e<=122||e>=161}const i=new t.Jq(((e,O)=>{for(let t=!1,o=0,r=0;;r++){let{next:i}=e;if(l(i)||45==i||95==i||t&&(a=i)>=48&&a<=57)!t&&(45!=i||r>0)&&(t=!0),o===r&&45==i&&o++,e.advance();else{if(92!=i||10==e.peek(1)){t&&e.acceptToken(40==i?97:2==o&&O.canShift(2)?2:98);break}e.advance(),e.next>-1&&e.advance(),t=!0}}var a})),n=new t.Jq((e=>{if(r.includes(e.peek(-1))){let{next:O}=e;(l(O)||95==O||35==O||46==O||91==O||58==O||45==O||38==O)&&e.acceptToken(96)}})),s=new t.Jq((e=>{if(!r.includes(e.peek(-1))){let{next:O}=e;if(37==O&&(e.advance(),e.acceptToken(1)),l(O)){do{e.advance()}while(l(e.next));e.acceptToken(1)}}})),d=(0,o.Gv)({"AtKeyword import charset namespace keyframes media supports":o.pJ.definitionKeyword,"from to selector":o.pJ.keyword,NamespaceName:o.pJ.namespace,KeyframeName:o.pJ.labelName,KeyframeRangeName:o.pJ.operatorKeyword,TagName:o.pJ.tagName,ClassName:o.pJ.className,PseudoClassName:o.pJ.constant(o.pJ.className),IdName:o.pJ.labelName,"FeatureName PropertyName":o.pJ.propertyName,AttributeName:o.pJ.attributeName,NumberLiteral:o.pJ.number,KeywordQuery:o.pJ.keyword,UnaryQueryOp:o.pJ.operatorKeyword,"CallTag ValueName":o.pJ.atom,VariableName:o.pJ.variableName,Callee:o.pJ.operatorKeyword,Unit:o.pJ.unit,"UniversalSelector NestingSelector":o.pJ.definitionOperator,MatchOp:o.pJ.compareOperator,"ChildOp SiblingOp, LogicOp":o.pJ.logicOperator,BinOp:o.pJ.arithmeticOperator,Important:o.pJ.modifier,Comment:o.pJ.blockComment,ColorLiteral:o.pJ.color,"ParenthesizedContent StringLiteral":o.pJ.string,":":o.pJ.punctuation,"PseudoOp #":o.pJ.derefOperator,"; ,":o.pJ.separator,"( )":o.pJ.paren,"[ ]":o.pJ.squareBracket,"{ }":o.pJ.brace}),c={__proto__:null,lang:32,"nth-child":32,"nth-last-child":32,"nth-of-type":32,"nth-last-of-type":32,dir:32,"host-context":32,url:60,"url-prefix":60,domain:60,regexp:60,selector:134},p={__proto__:null,"@import":114,"@media":138,"@charset":142,"@namespace":146,"@keyframes":152,"@supports":164},Q={__proto__:null,not:128,only:128},u=t.WQ.deserialize({version:14,states:"9bQYQ[OOO#_Q[OOP#fOWOOOOQP'#Cd'#CdOOQP'#Cc'#CcO#kQ[O'#CfO$_QXO'#CaO$fQ[O'#ChO$qQ[O'#DPO$vQ[O'#DTOOQP'#Ej'#EjO${QdO'#DeO%gQ[O'#DrO${QdO'#DtO%xQ[O'#DvO&TQ[O'#DyO&]Q[O'#EPO&kQ[O'#EROOQS'#Ei'#EiOOQS'#EU'#EUQYQ[OOO&rQXO'#CdO'gQWO'#DaO'lQWO'#EpO'wQ[O'#EpQOQWOOP(RO#tO'#C_POOO)C@X)C@XOOQP'#Cg'#CgOOQP,59Q,59QO#kQ[O,59QO(^Q[O'#EXO(xQWO,58{O)QQ[O,59SO$qQ[O,59kO$vQ[O,59oO(^Q[O,59sO(^Q[O,59uO(^Q[O,59vO)]Q[O'#D`OOQS,58{,58{OOQP'#Ck'#CkOOQO'#C}'#C}OOQP,59S,59SO)dQWO,59SO)iQWO,59SOOQP'#DR'#DROOQP,59k,59kOOQO'#DV'#DVO)nQ`O,59oOOQS'#Cp'#CpO${QdO'#CqO)vQvO'#CsO+TQtO,5:POOQO'#Cx'#CxO)iQWO'#CwO+iQWO'#CyOOQS'#Em'#EmOOQO'#Dh'#DhO+nQ[O'#DoO+|QWO'#EqO&]Q[O'#DmO,[QWO'#DpOOQO'#Er'#ErO({QWO,5:^O,aQpO,5:`OOQS'#Dx'#DxO,iQWO,5:bO,nQ[O,5:bOOQO'#D{'#D{O,vQWO,5:eO,{QWO,5:kO-TQWO,5:mOOQS-E8S-E8SO${QdO,59{O-]Q[O'#EZO-jQWO,5;[O-jQWO,5;[POOO'#ET'#ETP-uO#tO,58yPOOO,58y,58yOOQP1G.l1G.lO.lQXO,5:sOOQO-E8V-E8VOOQS1G.g1G.gOOQP1G.n1G.nO)dQWO1G.nO)iQWO1G.nOOQP1G/V1G/VO.yQ`O1G/ZO/dQXO1G/_O/zQXO1G/aO0bQXO1G/bO0xQWO,59zO0}Q[O'#DOO1UQdO'#CoOOQP1G/Z1G/ZO${QdO1G/ZO1]QpO,59]OOQS,59_,59_O${QdO,59aO1eQWO1G/kOOQS,59c,59cO1jQ!bO,59eO1rQWO'#DhO1}QWO,5:TO2SQWO,5:ZO&]Q[O,5:VO&]Q[O'#E[O2[QWO,5;]O2gQWO,5:XO(^Q[O,5:[OOQS1G/x1G/xOOQS1G/z1G/zOOQS1G/|1G/|O2xQWO1G/|O2}QdO'#D|OOQS1G0P1G0POOQS1G0V1G0VOOQS1G0X1G0XO3YQtO1G/gOOQO,5:u,5:uO3pQ[O,5:uOOQO-E8X-E8XO3}QWO1G0vPOOO-E8R-E8RPOOO1G.e1G.eOOQP7+$Y7+$YOOQP7+$u7+$uO${QdO7+$uOOQS1G/f1G/fO4YQXO'#EoO4aQWO,59jO4fQtO'#EVO5ZQdO'#ElO5eQWO,59ZO5jQpO7+$uOOQS1G.w1G.wOOQS1G.{1G.{OOQS7+%V7+%VO5rQWO1G/PO${QdO1G/oOOQO1G/u1G/uOOQO1G/q1G/qO5wQWO,5:vOOQO-E8Y-E8YO6VQXO1G/vOOQS7+%h7+%hO6^QYO'#CsOOQO'#EO'#EOO6iQ`O'#D}OOQO'#D}'#D}O6tQWO'#E]O6|QdO,5:hOOQS,5:h,5:hO7XQtO'#EYO${QdO'#EYO8VQdO7+%ROOQO7+%R7+%ROOQO1G0a1G0aO8jQpO<T![;'S%^;'S;=`%o<%lO%^l;TUo`Oy%^z!Q%^!Q![;g![;'S%^;'S;=`%o<%lO%^l;nYo`#b[Oy%^z!Q%^!Q![;g![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^l[[o`#b[Oy%^z!O%^!O!P;g!P!Q%^!Q![>T![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^n?VSp^Oy%^z;'S%^;'S;=`%o<%lO%^l?hWjWOy%^z!O%^!O!P;O!P!Q%^!Q![>T![;'S%^;'S;=`%o<%lO%^n@VU#_QOy%^z!Q%^!Q![;g![;'S%^;'S;=`%o<%lO%^~@nTjWOy%^z{@}{;'S%^;'S;=`%o<%lO%^~AUSo`#X~Oy%^z;'S%^;'S;=`%o<%lO%^lAg[#b[Oy%^z!O%^!O!P;g!P!Q%^!Q![>T![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^bBbU]QOy%^z![%^![!]Bt!];'S%^;'S;=`%o<%lO%^bB{S^Qo`Oy%^z;'S%^;'S;=`%o<%lO%^nC^S!W^Oy%^z;'S%^;'S;=`%o<%lO%^dCoSzSOy%^z;'S%^;'S;=`%o<%lO%^bDQU|QOy%^z!`%^!`!aDd!a;'S%^;'S;=`%o<%lO%^bDkS|Qo`Oy%^z;'S%^;'S;=`%o<%lO%^bDzWOy%^z!c%^!c!}Ed!}#T%^#T#oEd#o;'S%^;'S;=`%o<%lO%^bEk[!YQo`Oy%^z}%^}!OEd!O!Q%^!Q![Ed![!c%^!c!}Ed!}#T%^#T#oEd#o;'S%^;'S;=`%o<%lO%^bFfSxQOy%^z;'S%^;'S;=`%o<%lO%^lFwSv[Oy%^z;'S%^;'S;=`%o<%lO%^bGWUOy%^z#b%^#b#cGj#c;'S%^;'S;=`%o<%lO%^bGoUo`Oy%^z#W%^#W#XHR#X;'S%^;'S;=`%o<%lO%^bHYS!`Qo`Oy%^z;'S%^;'S;=`%o<%lO%^bHiUOy%^z#f%^#f#gHR#g;'S%^;'S;=`%o<%lO%^fIQS!RUOy%^z;'S%^;'S;=`%o<%lO%^nIcS!Q^Oy%^z;'S%^;'S;=`%o<%lO%^fItU!PQOy%^z!_%^!_!`6y!`;'S%^;'S;=`%o<%lO%^`JZP;=`<%l$}",tokenizers:[n,s,i,1,2,3,4,new t.RA("m~RRYZ[z{a~~g~aO#Z~~dP!P!Qg~lO#[~~",28,102)],topRules:{StyleSheet:[0,4],Styles:[1,84]},specialized:[{term:97,get:e=>c[e]||-1},{term:56,get:e=>p[e]||-1},{term:98,get:e=>Q[e]||-1}],tokenPrec:1169});var m=a(77120),S=a(21649);let b=null;function g(){if(!b&&"object"==typeof document&&document.body){let{style:e}=document.body,O=[],a=new Set;for(let t in e)"cssText"!=t&&"cssFloat"!=t&&"string"==typeof e[t]&&(/[A-Z]/.test(t)&&(t=t.replace(/[A-Z]/g,(e=>"-"+e.toLowerCase()))),a.has(t)||(O.push(t),a.add(t)));b=O.sort().map((e=>({type:"property",label:e})))}return b||[]}const h=["active","after","any-link","autofill","backdrop","before","checked","cue","default","defined","disabled","empty","enabled","file-selector-button","first","first-child","first-letter","first-line","first-of-type","focus","focus-visible","focus-within","fullscreen","has","host","host-context","hover","in-range","indeterminate","invalid","is","lang","last-child","last-of-type","left","link","marker","modal","not","nth-child","nth-last-child","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","part","placeholder","placeholder-shown","read-only","read-write","required","right","root","scope","selection","slotted","target","target-text","valid","visited","where"].map((e=>({type:"class",label:e}))),y=["above","absolute","activeborder","additive","activecaption","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","antialiased","appworkspace","asterisks","attr","auto","auto-flow","avoid","avoid-column","avoid-page","avoid-region","axis-pan","background","backwards","baseline","below","bidi-override","blink","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","bullets","button","button-bevel","buttonface","buttonhighlight","buttonshadow","buttontext","calc","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","clear","clip","close-quote","col-resize","collapse","color","color-burn","color-dodge","column","column-reverse","compact","condensed","contain","content","contents","content-box","context-menu","continuous","copy","counter","counters","cover","crop","cross","crosshair","currentcolor","cursive","cyclic","darken","dashed","decimal","decimal-leading-zero","default","default-button","dense","destination-atop","destination-in","destination-out","destination-over","difference","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic-abegede-gez","ethiopic-halehame-aa-er","ethiopic-halehame-gez","ew-resize","exclusion","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fill-box","fixed","flat","flex","flex-end","flex-start","footnotes","forwards","from","geometricPrecision","graytext","grid","groove","hand","hard-light","help","hidden","hide","higher","highlight","highlighttext","horizontal","hsl","hsla","hue","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-grid","inline-table","inset","inside","intrinsic","invert","italic","justify","keep-all","landscape","large","larger","left","level","lighter","lighten","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-hexadecimal","lower-latin","lower-norwegian","lowercase","ltr","luminosity","manipulation","match","matrix","matrix3d","medium","menu","menutext","message-box","middle","min-intrinsic","mix","monospace","move","multiple","multiple_mask_images","multiply","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","opacity","open-quote","optimizeLegibility","optimizeSpeed","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","perspective","pinch-zoom","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row","row-resize","row-reverse","rtl","run-in","running","s-resize","sans-serif","saturation","scale","scale3d","scaleX","scaleY","scaleZ","screen","scroll","scrollbar","scroll-position","se-resize","self-start","self-end","semi-condensed","semi-expanded","separate","serif","show","single","skew","skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","soft-light","solid","source-atop","source-in","source-out","source-over","space","space-around","space-between","space-evenly","spell-out","square","start","static","status-bar","stretch","stroke","stroke-box","sub","subpixel-antialiased","svg_masks","super","sw-resize","symbolic","symbols","system-ui","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","text","text-bottom","text-top","textarea","textfield","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","to","top","transform","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","unidirectional-pan","unset","up","upper-latin","uppercase","url","var","vertical","vertical-text","view-box","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","wrap","wrap-reverse","x-large","x-small","xor","xx-large","xx-small"].map((e=>({type:"keyword",label:e}))).concat(["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"].map((e=>({type:"constant",label:e})))),$=["a","abbr","address","article","aside","b","bdi","bdo","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","dd","del","details","dfn","dialog","div","dl","dt","em","figcaption","figure","footer","form","header","hgroup","h1","h2","h3","h4","h5","h6","hr","html","i","iframe","img","input","ins","kbd","label","legend","li","main","meter","nav","ol","output","p","pre","ruby","section","select","small","source","span","strong","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","tr","u","ul"].map((e=>({type:"type",label:e}))),f=/^(\w[\w-]*|-\w[\w-]*|)$/,P=/^-(-[\w-]*)?$/,w=new S.hr,k=["Declaration"];function v(e){for(let O=e;;){if(O.type.isTop)return O;if(!(O=O.parent))return e}}function z(e,O,a){if(O.to-O.from>4096){let t=w.get(O);if(t)return t;let o=[],r=new Set,l=O.cursor(S.vj.IncludeAnonymous);if(l.firstChild())do{for(let O of z(e,l.node,a))r.has(O.label)||(r.add(O.label),o.push(O))}while(l.nextSibling());return w.set(O,o),o}{let t=[],o=new Set;return O.cursor().iterate((O=>{var r;if(a(O)&&O.matchContext(k)&&":"==(null===(r=O.node.nextSibling)||void 0===r?void 0:r.name)){let a=e.sliceString(O.from,O.to);o.has(a)||(o.add(a),t.push({label:a,type:"variable"}))}})),t}}const R=e=>O=>{let{state:a,pos:t}=O,o=(0,m.qz)(a).resolveInner(t,-1),r=o.type.isError&&o.from==o.to-1&&"-"==a.doc.sliceString(o.from,o.to);if("PropertyName"==o.name||(r||"TagName"==o.name)&&/^(Block|Styles)$/.test(o.resolve(o.to).name))return{from:o.from,options:g(),validFor:f};if("ValueName"==o.name)return{from:o.from,options:y,validFor:f};if("PseudoClassName"==o.name)return{from:o.from,options:h,validFor:f};if(e(o)||(O.explicit||r)&&function(e,O){var a;if(("("==e.name||e.type.isError)&&(e=e.parent||e),"ArgList"!=e.name)return!1;let t=null===(a=e.parent)||void 0===a?void 0:a.firstChild;return"Callee"==(null==t?void 0:t.name)&&"var"==O.sliceString(t.from,t.to)}(o,a.doc))return{from:e(o)||r?o.from:t,options:z(a.doc,v(o),e),validFor:P};if("TagName"==o.name){for(let{parent:e}=o;e;e=e.parent)if("Block"==e.name)return{from:o.from,options:g(),validFor:f};return{from:o.from,options:$,validFor:f}}if(!O.explicit)return null;let l=o.resolve(t),i=l.childBefore(t);return i&&":"==i.name&&"PseudoClassSelector"==l.name?{from:t,options:h,validFor:f}:i&&":"==i.name&&"Declaration"==l.name||"ArgList"==l.name?{from:t,options:y,validFor:f}:"Block"==l.name||"Styles"==l.name?{from:t,options:g(),validFor:f}:null},W=R((e=>"VariableName"==e.name)),X=m.qp.define({name:"css",parser:u.configure({props:[m.uj.add({Declaration:(0,m.tC)()}),m.x0.add({"Block KeyframeList":m.Dv})]}),languageData:{commentTokens:{block:{open:"/*",close:"*/"}},indentOnInput:/^\s*\}$/,wordChars:"-"}});function x(){return new m.ri(X,X.data.of({autocomplete:W}))}}}]);
+//# sourceMappingURL=4211.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/4211.index.js.map b/book/_build/html/_static/4211.index.js.map
new file mode 100644
index 0000000..60c354a
--- /dev/null
+++ b/book/_build/html/_static/4211.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"4211.index.js","mappings":"8NAIA,MASMA,EAAQ,CAAC,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KACrE,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,OAIrE,SAASC,EAAQC,GAAM,OAAOA,GAAM,IAAMA,GAAM,IAAMA,GAAM,IAAMA,GAAM,KAAOA,GAAM,GAAI,CAIzF,MAAMC,EAAc,IAAI,MAAkB,CAACC,EAAOC,KAChD,IAAK,IAAIC,GAAS,EAAOC,EAAS,EAAGC,EAAI,GAAIA,IAAK,CAChD,IAAI,KAACC,GAAQL,EACb,GAAIH,EAAQQ,IAVsD,IAU7CA,GAVmB,IAUHA,GAAuBH,IAL/CJ,EAKiEO,IAL9C,IAAMP,GAAM,IAMrCI,IAX2D,IAWhDG,GAAgBD,EAAI,KAAIF,GAAS,GAC7CC,IAAWC,GAZiD,IAY5CC,GAAcF,IAClCH,EAAMM,cACD,IAbgD,IAa5CD,GAb0D,IAarCL,EAAMO,KAAK,GAIpC,CACDL,GACFF,EAAMQ,YApBa,IAoBDH,EA7Bf,GA6BmD,GAAVF,GAAeF,EAAMQ,SA3BxD,KADF,IA6BT,KACF,CAPET,EAAMM,UACFN,EAAMK,MAAQ,GAAGL,EAAMM,UAC3BJ,GAAS,CAKX,CACF,CAlBF,IAAiBJ,CAkBf,IAGIY,EAAa,IAAI,MAAkBV,IACvC,GAAIJ,EAAMe,SAASX,EAAMO,MAAM,IAAK,CAClC,IAAI,KAACF,GAAQL,GACTH,EAAQQ,IA7B4B,IA6BnBA,GA5BZ,IA4BkCA,GA7BoC,IA6BpBA,GA7BJ,IA8BnDA,GA9BM,IA8BcA,GA9B0C,IA8BzBA,GA7BF,IA6BkBA,IACvDL,EAAMQ,YA1CS,GA2CnB,KAGII,EAAY,IAAI,MAAkBZ,IACtC,IAAKJ,EAAMe,SAASX,EAAMO,MAAM,IAAK,CACnC,IAAI,KAACF,GAAQL,EAEb,GAtCuB,IAqCnBK,IAAmBL,EAAMM,UAAWN,EAAMQ,YAhDzC,IAiDDX,EAAQQ,GAAO,CACjB,GAAKL,EAAMM,gBAAoBT,EAAQG,EAAMK,OAC7CL,EAAMQ,YAnDH,EAoDL,CACF,KAGIK,GAAkB,QAAU,CAChC,8DAA+D,uBAC/D,mBAAoB,aACpBC,cAAe,eACfC,aAAc,eACdC,kBAAmB,qBACnBC,QAAS,aACTC,UAAW,eACXC,gBAAiB,cAAc,gBAC/BC,OAAQ,eACR,2BAA4B,kBAC5BC,cAAe,mBACfC,cAAe,YACfC,aAAc,aACdC,aAAc,qBACd,oBAAqB,UACrBC,aAAc,kBACdC,OAAQ,qBACRC,KAAM,UACN,oCAAqC,wBACrCC,QAAS,qBACT,6BAA8B,mBAC9BC,MAAO,wBACPC,UAAW,cACXC,QAAS,kBACTC,aAAc,WACd,qCAAsC,YACtC,IAAK,iBACL,aAAc,mBACd,MAAO,eACP,MAAO,WACP,MAAO,mBACP,MAAO,aAIHC,EAAc,CAACC,UAAU,KAAKC,KAAK,GAAI,YAAY,GAAI,iBAAiB,GAAI,cAAc,GAAI,mBAAmB,GAAIC,IAAI,GAAI,eAAe,GAAIC,IAAI,GAAI,aAAa,GAAIC,OAAO,GAAIC,OAAO,GAAIC,SAAS,KACxMC,EAAiB,CAACP,UAAU,KAAK,UAAU,IAAK,SAAS,IAAK,WAAW,IAAK,aAAa,IAAK,aAAa,IAAK,YAAY,KAC9HQ,EAAkB,CAACR,UAAU,KAAKS,IAAI,IAAKC,KAAK,KAChDC,EAAS,iBAAqB,CAClCC,QAAS,GACTC,OAAQ,49DACRC,UAAW,kiDACXC,KAAM,q2BACNC,UAAW,q6BACXC,QAAS,IACTC,UAAW,CACT,CAAC,WAAY,GAAG,IAAI,GAAG,KACvB,CAAC,WAAY,GAAG,IAAI,GAAG,MAEzBC,YAAa,CAACxC,GACdyC,aAAc,CAAC,EAAE,EAAE,IACnBC,gBAAiB,GACjBC,UAAW,i+GACXC,WAAY,CAAC/C,EAAYE,EAAWb,EAAa,EAAG,EAAG,EAAG,EAAG,IAAI,KAAgB,qCAAsC,GAAI,MAC3H2D,SAAU,CAAC,WAAa,CAAC,EAAE,GAAG,OAAS,CAAC,EAAE,KAC1CC,YAAa,CAAC,CAACC,KAAM,GAAIC,IAAMC,GAAU7B,EAAY6B,KAAW,GAAG,CAACF,KAAM,GAAIC,IAAMC,GAAUrB,EAAeqB,KAAW,GAAG,CAACF,KAAM,GAAIC,IAAMC,GAAUpB,EAAgBoB,KAAW,IACjLC,UAAW,O,0BClHb,IAAIC,EAAc,KAClB,SAASC,IACL,IAAKD,GAAkC,iBAAZE,UAAwBA,SAASC,KAAM,CAC9D,IAAI,MAAEC,GAAUF,SAASC,KAAME,EAAQ,GAAIC,EAAO,IAAIC,IACtD,IAAK,IAAIC,KAAQJ,EACD,WAARI,GAA6B,YAARA,GACK,iBAAfJ,EAAMI,KACT,QAAQC,KAAKD,KACbA,EAAOA,EAAKE,QAAQ,UAAU5E,GAAM,IAAMA,EAAG6E,iBAC5CL,EAAKM,IAAIJ,KACVH,EAAMQ,KAAKL,GACXF,EAAKQ,IAAIN,KAIzBR,EAAcK,EAAMU,OAAOC,KAAIC,IAAQ,CAAGC,KAAM,WAAYC,MAAOF,KACvE,CACA,OAAOjB,GAAe,EAC1B,CACA,MAAMoB,EAA6B,CAC/B,SAAU,QAAS,WAAY,WAAY,WAAY,SACvD,UAAW,MAAO,UAAW,UAAW,WAAY,QACpD,UAAW,uBAAwB,QAAS,cAC5C,eAAgB,aAAc,gBAAiB,QAC/C,gBAAiB,eAAgB,aAAc,MAAO,OACtD,eAAgB,QAAS,WAAY,gBAAiB,UACtD,KAAM,OAAQ,aAAc,eAAgB,OAAQ,OAAQ,SAC5D,QAAS,MAAO,YAAa,iBAAkB,mBAC/C,cAAe,aAAc,eAAgB,WAAY,eACzD,OAAQ,cAAe,oBAAqB,YAAa,aACzD,WAAY,QAAS,OAAQ,QAAS,YAAa,UAAW,SAC9D,cAAe,QAAS,UAAW,SACrCJ,KAAIC,IAAQ,CAAGC,KAAM,QAASC,MAAOF,MACjCI,EAAsB,CACxB,QAAS,WAAY,eAAgB,WAAY,gBAAiB,oBAClE,QAAS,QAAS,MAAO,aAAc,aAAc,YAAa,SAClE,cAAe,eAAgB,YAAa,OAAQ,OAAQ,YAAa,QAAS,eAClF,aAAc,eAAgB,WAAY,aAAc,YAAa,WAAY,QACjF,gBAAiB,QAAS,QAAS,aAAc,OAAQ,SAAU,SAAU,aAC7E,OAAQ,SAAU,QAAS,YAAa,aAAc,UAAW,SAAU,eAC3E,aAAc,kBAAmB,eAAgB,aAAc,OAAQ,aACvE,sBAAuB,UAAW,cAAe,QAAS,OAAQ,SAAU,WAAY,SACxF,cAAe,QAAS,OAAQ,cAAe,aAAc,WAAY,QAAS,aAClF,cAAe,SAAU,iBAAkB,UAAW,YAAa,UAAW,UAC9E,WAAY,cAAe,eAAgB,aAAc,OAAQ,UAAW,WAAY,QACxF,OAAQ,QAAS,YAAa,eAAgB,UAAW,SAAU,SAAU,SAAU,UACvF,uBAAwB,UAAW,iBAAkB,QAAS,mBAAoB,iBAClF,kBAAmB,mBAAoB,aAAc,OAAQ,UAAW,oBACxE,kBAAmB,WAAY,WAAY,eAAgB,SAAU,SAAU,OAAQ,WACvF,OAAQ,UAAW,cAAe,WAAY,UAAW,UAAW,WAAY,QAAS,MACzF,uBAAwB,0BAA2B,wBAAyB,YAAa,YACzF,WAAY,UAAW,kBAAmB,iBAAkB,UAAW,OAAQ,OAAQ,WACvF,QAAS,OAAQ,OAAQ,WAAY,aAAc,YAAa,WAAY,OAC5E,qBAAsB,WAAY,OAAQ,SAAU,OAAQ,aAAc,OAAQ,SAAU,OAC5F,SAAU,YAAa,gBAAiB,aAAc,MAAO,OAAQ,MAAO,OAAQ,SACpF,iBAAkB,kBAAmB,sBAAuB,WAAY,iBAAkB,WAC1F,UAAW,UAAW,SAAU,cAAe,eAAgB,cAAe,cAC9E,eAAgB,QAAS,SAAU,YAAa,SAAU,SAAU,UAAW,WAC/E,YAAa,QAAS,SAAU,OAAQ,QAAS,UAAW,UAAW,eAAgB,SACvF,kBAAmB,QAAS,YAAa,UAAW,WAAY,QAAS,UAAW,OAAQ,QAC5F,oBAAqB,cAAe,kBAAmB,YAAa,MAAO,aAAc,eACzF,QAAS,SAAU,WAAY,SAAU,OAAQ,WAAY,cAAe,SAAU,gBACtF,MAAO,YAAa,OAAQ,WAAY,uBAAwB,WAAY,WAAY,WACxF,YAAa,cAAe,iBAAkB,UAAW,gBAAiB,YAAa,OACvF,SAAU,cAAe,SAAU,YAAa,UAAW,UAAW,YAAa,cACnF,UAAW,UAAW,aAAc,qBAAsB,gBAAiB,SAAU,UACrF,gBAAiB,UAAW,WAAY,UAAW,cAAe,UAAW,OAAQ,SACrF,cAAe,aAAc,cAAe,eAAgB,UAAW,UAAW,WAClF,MAAO,WAAY,WAAY,cAAe,WAAY,cAAe,kBAAmB,QAC5F,YAAa,aAAc,4BAA6B,YAAa,SAAU,WAAY,SAC3F,4BAA6B,4BAA6B,WAAY,WAAY,QAAS,UAC3F,MAAO,OAAQ,QAAS,QAAS,SAAU,WAAY,UAAW,UAAW,UAAW,QACxF,MAAO,aAAc,cAAe,MAAO,SAAU,UAAW,WAAY,aAAc,aAC1F,QAAS,UAAW,SAAU,SAAU,SAAU,SAAU,SAAU,YAAa,kBACnF,YAAa,aAAc,WAAY,iBAAkB,gBAAiB,WAAY,QAAS,OAC/F,SAAU,OAAQ,QAAS,QAAS,mBAAoB,QAAS,oBACjE,kBAAmB,yBAA0B,uBAAwB,OAAQ,QAAS,aACtF,gBAAiB,UAAW,aAAc,QAAS,cAAe,YAAa,aAC/E,cAAe,QAAS,eAAgB,gBAAiB,eAAgB,YAAa,SAAU,QAChG,SAAU,aAAc,UAAW,SAAU,aAAc,MAAO,uBAAwB,YAC1F,QAAS,YAAa,WAAY,UAAW,YAAa,QAAS,gBAAiB,aACpF,eAAgB,qBAAsB,qBAAsB,qBAAsB,YAClF,kBAAmB,OAAQ,cAAe,WAAY,WAAY,YAAa,QAAS,OACxF,mBAAoB,aAAc,kBAAmB,oBAAqB,eAAgB,KAAM,MAChG,YAAa,YAAa,cAAe,aAAc,aAAc,aAAc,cACnF,kBAAmB,iBAAkB,YAAa,qBAAsB,QAAS,KAAM,cACvF,YAAa,MAAO,MAAO,WAAY,gBAAiB,WAAY,UAAW,cAC/E,iBAAkB,gBAAiB,SAAU,WAAY,OAAQ,OAAQ,QAAS,SAAU,cAC5F,aAAc,QAAS,OAAQ,eAAgB,UAAW,UAAW,MAAO,WAAY,YAC1FL,KAAIC,IAAQ,CAAGC,KAAM,UAAWC,MAAOF,MAASK,OAAoB,CAClE,YAAa,eAAgB,OAAQ,aAAc,QAAS,QAC5D,SAAU,QAAS,iBAAkB,OAAQ,aAAc,QAC3D,YAAa,YAAa,aAAc,YAAa,QAAS,iBAC9D,WAAY,UAAW,OAAQ,WAAY,WAAY,gBACvD,WAAY,YAAa,YAAa,cAAe,iBACrD,aAAc,aAAc,UAAW,aAAc,eACrD,gBAAiB,gBAAiB,gBAAiB,aACnD,WAAY,cAAe,UAAW,aAAc,YACpD,cAAe,cAAe,UAAW,YAAa,aACtD,OAAQ,YAAa,OAAQ,OAAQ,QAAS,cAAe,WAC7D,UAAW,YAAa,SAAU,QAAS,QAAS,WACpD,gBAAiB,YAAa,eAAgB,YAAa,aAC3D,YAAa,uBAAwB,YAAa,aAAc,YAChE,cAAe,gBAAiB,eAAgB,iBAChD,iBAAkB,cAAe,OAAQ,YAAa,QAAS,UAC/D,SAAU,mBAAoB,aAAc,eAAgB,eAC5D,iBAAkB,kBAAmB,oBAAqB,kBAC1D,kBAAmB,eAAgB,YAAa,YAAa,WAC7D,cAAe,OAAQ,UAAW,QAAS,YAAa,SAAU,YAClE,SAAU,gBAAiB,YAAa,gBAAiB,gBACzD,aAAc,YAAa,OAAQ,OAAQ,OAAQ,aACnD,SAAU,gBAAiB,MAAO,YAAa,YAAa,cAC5D,SAAU,aAAc,WAAY,WAAY,SAAU,SAAU,UACpE,YAAa,YAAa,OAAQ,cAAe,YAAa,MAC9D,OAAQ,UAAW,SAAU,YAAa,SAAU,QAAS,QAC7D,aAAc,SAAU,eAC1BN,KAAIC,IAAQ,CAAGC,KAAM,WAAYC,MAAOF,OACpCM,EAAoB,CACtB,IAAK,OAAQ,UAAW,UAAW,QAAS,IAAK,MAAO,MAAO,aAAc,OAC7E,KAAM,SAAU,SAAU,UAAW,OAAQ,OAAQ,MAAO,WAAY,KAAM,MAC9E,UAAW,MAAO,SAAU,MAAO,KAAM,KAAM,KAAM,aAAc,SAAU,SAC7E,OAAQ,SAAU,SAAU,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,OAAQ,IAAK,SACnF,MAAO,QAAS,MAAO,MAAO,QAAS,SAAU,KAAM,OAAQ,QAAS,MAAO,KAAM,SACrF,IAAK,MAAO,OAAQ,UAAW,SAAU,QAAS,SAAU,OAAQ,SAAU,MAAO,UACrF,MAAO,QAAS,QAAS,KAAM,WAAY,WAAY,QAAS,KAAM,QAAS,KAAM,IAAK,MAC5FP,KAAIC,IAAQ,CAAGC,KAAM,OAAQC,MAAOF,MAChC,EAAa,0BAA2BO,EAAW,gBAYnDC,EAA+B,IAAI,KACnCC,EAAe,CAAC,eACtB,SAASC,EAAOC,GACZ,IAAK,IAAIC,EAAMD,IAAQ,CACnB,GAAIC,EAAIX,KAAKY,MACT,OAAOD,EACX,KAAMA,EAAMA,EAAIE,QACZ,OAAOH,CACf,CACJ,CACA,SAASI,EAAcC,EAAKL,EAAMM,GAC9B,GAAIN,EAAKO,GAAKP,EAAKQ,KAAO,KAAM,CAC5B,IAAIC,EAAQZ,EAAgB5B,IAAI+B,GAChC,GAAIS,EACA,OAAOA,EACX,IAAIC,EAAS,GAAIhC,EAAO,IAAIC,IAAKgC,EAASX,EAAKW,OAAO,uBACtD,GAAIA,EAAOC,aACP,GACI,IAAK,IAAIC,KAAUT,EAAcC,EAAKM,EAAOX,KAAMM,GAC1C5B,EAAKM,IAAI6B,EAAOtB,SACjBb,EAAKQ,IAAI2B,EAAOtB,OAChBmB,EAAOzB,KAAK4B,UAEfF,EAAOG,eAEpB,OADAjB,EAAgBkB,IAAIf,EAAMU,GACnBA,CACX,CACK,CACD,IAAIA,EAAS,GAAIhC,EAAO,IAAIC,IAW5B,OAVAqB,EAAKW,SAASK,SAAQhB,IAClB,IAAIiB,EACJ,GAAIX,EAAWN,IAASA,EAAKkB,aAAapB,IAAgG,MAA7C,QAAhCmB,EAAKjB,EAAKA,KAAKc,mBAAgC,IAAPG,OAAgB,EAASA,EAAG5B,MAAc,CAC3I,IAAIA,EAAOgB,EAAIc,YAAYnB,EAAKQ,KAAMR,EAAKO,IACtC7B,EAAKM,IAAIK,KACVX,EAAKQ,IAAIG,GACTqB,EAAOzB,KAAK,CAAEM,MAAOF,EAAMC,KAAM,aAEzC,KAEGoB,CACX,CACJ,CAOA,MAAMU,EAA6Bd,GAAee,IAC9C,IAAI,MAAEC,EAAK,IAAEC,GAAQF,EAASrB,GAAO,QAAWsB,GAAOE,aAAaD,GAAM,GACtEE,EAASzB,EAAKV,KAAKoC,SAAW1B,EAAKQ,MAAQR,EAAKO,GAAK,GAAkD,KAA7Ce,EAAMjB,IAAIc,YAAYnB,EAAKQ,KAAMR,EAAKO,IACpG,GAAiB,gBAAbP,EAAKX,OACJoC,GAAuB,WAAbzB,EAAKX,OAAsB,mBAAmBR,KAAKmB,EAAK2B,QAAQ3B,EAAKO,IAAIlB,MACpF,MAAO,CAAEmB,KAAMR,EAAKQ,KAAMoB,QAASvD,IAAcwD,SAAU,GAC/D,GAAiB,aAAb7B,EAAKX,KACL,MAAO,CAAEmB,KAAMR,EAAKQ,KAAMoB,QAASnC,EAAQoC,SAAU,GACzD,GAAiB,mBAAb7B,EAAKX,KACL,MAAO,CAAEmB,KAAMR,EAAKQ,KAAMoB,QAASpC,EAAeqC,SAAU,GAChE,GAAIvB,EAAWN,KAAUqB,EAAQS,UAAYL,IArEjD,SAAkBzB,EAAMK,GACpB,IAAIY,EAGJ,IAFiB,KAAbjB,EAAKX,MAAeW,EAAKV,KAAKoC,WAC9B1B,EAAOA,EAAKG,QAAUH,GACT,WAAbA,EAAKX,KACL,OAAO,EACX,IAAI0C,EAAgC,QAAtBd,EAAKjB,EAAKG,cAA2B,IAAPc,OAAgB,EAASA,EAAGL,WACxE,MAAqE,WAAhEmB,aAAuC,EAASA,EAAO1C,OAEV,OAA3CgB,EAAIc,YAAYY,EAAOvB,KAAMuB,EAAOxB,GAC/C,CA2D4DyB,CAAShC,EAAMsB,EAAMjB,KACzE,MAAO,CAAEG,KAAMF,EAAWN,IAASyB,EAASzB,EAAKQ,KAAOe,EACpDK,QAASxB,EAAckB,EAAMjB,IAAKN,EAAOC,GAAOM,GAChDuB,SAAUjC,GAClB,GAAiB,WAAbI,EAAKX,KAAmB,CACxB,IAAK,IAAI,OAAEc,GAAWH,EAAMG,EAAQA,EAASA,EAAOA,OAChD,GAAmB,SAAfA,EAAOd,KACP,MAAO,CAAEmB,KAAMR,EAAKQ,KAAMoB,QAASvD,IAAcwD,SAAU,GACnE,MAAO,CAAErB,KAAMR,EAAKQ,KAAMoB,QAASjC,EAAMkC,SAAU,EACvD,CACA,IAAKR,EAAQS,SACT,OAAO,KACX,IAAIG,EAAQjC,EAAK2B,QAAQJ,GAAMW,EAASD,EAAME,YAAYZ,GAC1D,OAAIW,GAAyB,KAAfA,EAAO7C,MAA6B,uBAAd4C,EAAM5C,KAC/B,CAAEmB,KAAMe,EAAKK,QAASpC,EAAeqC,SAAU,GACtDK,GAAyB,KAAfA,EAAO7C,MAA6B,eAAd4C,EAAM5C,MAAuC,WAAd4C,EAAM5C,KAC9D,CAAEmB,KAAMe,EAAKK,QAASnC,EAAQoC,SAAU,GACjC,SAAdI,EAAM5C,MAAiC,UAAd4C,EAAM5C,KACxB,CAAEmB,KAAMe,EAAKK,QAASvD,IAAcwD,SAAU,GAClD,IAAI,EAKTO,EAAmChB,GAA0BiB,GAAe,gBAAVA,EAAEhD,OAOpEiD,EAA2B,YAAkB,CAC/CjD,KAAM,MACNpC,OAAqBA,EAAOsF,UAAU,CAClCC,MAAO,CACU,SAAmB,CAC5BC,aAA0B,YAEjB,SAAiB,CAC1B,qBAAsB,UAIlCC,aAAc,CACVC,cAAe,CAAEC,MAAO,CAAEC,KAAM,KAAMC,MAAO,OAC7CC,cAAe,UACfC,UAAW,OAMnB,SAASC,IACL,OAAO,IAAI,KAAgBX,EAAaA,EAAYY,KAAKC,GAAG,CAAEC,aAAchB,IAChF,C","sources":["webpack://thebe/../../node_modules/@lezer/css/dist/index.js","webpack://thebe/../../node_modules/@codemirror/lang-css/dist/index.js"],"sourcesContent":["import { ExternalTokenizer, LRParser, LocalTokenGroup } from '@lezer/lr';\nimport { styleTags, tags } from '@lezer/highlight';\n\n// This file was generated by lezer-generator. You probably shouldn't edit it.\nconst descendantOp = 96,\n Unit = 1,\n callee = 97,\n identifier = 98,\n VariableName = 2;\n\n/* Hand-written tokenizers for CSS tokens that can't be\n expressed by Lezer's built-in tokenizer. */\n\nconst space = [9, 10, 11, 12, 13, 32, 133, 160, 5760, 8192, 8193, 8194, 8195, 8196, 8197,\n 8198, 8199, 8200, 8201, 8202, 8232, 8233, 8239, 8287, 12288];\nconst colon = 58, parenL = 40, underscore = 95, bracketL = 91, dash = 45, period = 46,\n hash = 35, percent = 37, ampersand = 38, backslash = 92, newline = 10;\n\nfunction isAlpha(ch) { return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch >= 161 }\n\nfunction isDigit(ch) { return ch >= 48 && ch <= 57 }\n\nconst identifiers = new ExternalTokenizer((input, stack) => {\n for (let inside = false, dashes = 0, i = 0;; i++) {\n let {next} = input;\n if (isAlpha(next) || next == dash || next == underscore || (inside && isDigit(next))) {\n if (!inside && (next != dash || i > 0)) inside = true;\n if (dashes === i && next == dash) dashes++;\n input.advance();\n } else if (next == backslash && input.peek(1) != newline) {\n input.advance();\n if (input.next > -1) input.advance();\n inside = true;\n } else {\n if (inside)\n input.acceptToken(next == parenL ? callee : dashes == 2 && stack.canShift(VariableName) ? VariableName : identifier);\n break\n }\n }\n});\n\nconst descendant = new ExternalTokenizer(input => {\n if (space.includes(input.peek(-1))) {\n let {next} = input;\n if (isAlpha(next) || next == underscore || next == hash || next == period ||\n next == bracketL || next == colon || next == dash || next == ampersand)\n input.acceptToken(descendantOp);\n }\n});\n\nconst unitToken = new ExternalTokenizer(input => {\n if (!space.includes(input.peek(-1))) {\n let {next} = input;\n if (next == percent) { input.advance(); input.acceptToken(Unit); }\n if (isAlpha(next)) {\n do { input.advance(); } while (isAlpha(input.next))\n input.acceptToken(Unit);\n }\n }\n});\n\nconst cssHighlighting = styleTags({\n \"AtKeyword import charset namespace keyframes media supports\": tags.definitionKeyword,\n \"from to selector\": tags.keyword,\n NamespaceName: tags.namespace,\n KeyframeName: tags.labelName,\n KeyframeRangeName: tags.operatorKeyword,\n TagName: tags.tagName,\n ClassName: tags.className,\n PseudoClassName: tags.constant(tags.className),\n IdName: tags.labelName,\n \"FeatureName PropertyName\": tags.propertyName,\n AttributeName: tags.attributeName,\n NumberLiteral: tags.number,\n KeywordQuery: tags.keyword,\n UnaryQueryOp: tags.operatorKeyword,\n \"CallTag ValueName\": tags.atom,\n VariableName: tags.variableName,\n Callee: tags.operatorKeyword,\n Unit: tags.unit,\n \"UniversalSelector NestingSelector\": tags.definitionOperator,\n MatchOp: tags.compareOperator,\n \"ChildOp SiblingOp, LogicOp\": tags.logicOperator,\n BinOp: tags.arithmeticOperator,\n Important: tags.modifier,\n Comment: tags.blockComment,\n ColorLiteral: tags.color,\n \"ParenthesizedContent StringLiteral\": tags.string,\n \":\": tags.punctuation,\n \"PseudoOp #\": tags.derefOperator,\n \"; ,\": tags.separator,\n \"( )\": tags.paren,\n \"[ ]\": tags.squareBracket,\n \"{ }\": tags.brace\n});\n\n// This file was generated by lezer-generator. You probably shouldn't edit it.\nconst spec_callee = {__proto__:null,lang:32, \"nth-child\":32, \"nth-last-child\":32, \"nth-of-type\":32, \"nth-last-of-type\":32, dir:32, \"host-context\":32, url:60, \"url-prefix\":60, domain:60, regexp:60, selector:134};\nconst spec_AtKeyword = {__proto__:null,\"@import\":114, \"@media\":138, \"@charset\":142, \"@namespace\":146, \"@keyframes\":152, \"@supports\":164};\nconst spec_identifier = {__proto__:null,not:128, only:128};\nconst parser = LRParser.deserialize({\n version: 14,\n states: \"9bQYQ[OOO#_Q[OOP#fOWOOOOQP'#Cd'#CdOOQP'#Cc'#CcO#kQ[O'#CfO$_QXO'#CaO$fQ[O'#ChO$qQ[O'#DPO$vQ[O'#DTOOQP'#Ej'#EjO${QdO'#DeO%gQ[O'#DrO${QdO'#DtO%xQ[O'#DvO&TQ[O'#DyO&]Q[O'#EPO&kQ[O'#EROOQS'#Ei'#EiOOQS'#EU'#EUQYQ[OOO&rQXO'#CdO'gQWO'#DaO'lQWO'#EpO'wQ[O'#EpQOQWOOP(RO#tO'#C_POOO)C@X)C@XOOQP'#Cg'#CgOOQP,59Q,59QO#kQ[O,59QO(^Q[O'#EXO(xQWO,58{O)QQ[O,59SO$qQ[O,59kO$vQ[O,59oO(^Q[O,59sO(^Q[O,59uO(^Q[O,59vO)]Q[O'#D`OOQS,58{,58{OOQP'#Ck'#CkOOQO'#C}'#C}OOQP,59S,59SO)dQWO,59SO)iQWO,59SOOQP'#DR'#DROOQP,59k,59kOOQO'#DV'#DVO)nQ`O,59oOOQS'#Cp'#CpO${QdO'#CqO)vQvO'#CsO+TQtO,5:POOQO'#Cx'#CxO)iQWO'#CwO+iQWO'#CyOOQS'#Em'#EmOOQO'#Dh'#DhO+nQ[O'#DoO+|QWO'#EqO&]Q[O'#DmO,[QWO'#DpOOQO'#Er'#ErO({QWO,5:^O,aQpO,5:`OOQS'#Dx'#DxO,iQWO,5:bO,nQ[O,5:bOOQO'#D{'#D{O,vQWO,5:eO,{QWO,5:kO-TQWO,5:mOOQS-E8S-E8SO${QdO,59{O-]Q[O'#EZO-jQWO,5;[O-jQWO,5;[POOO'#ET'#ETP-uO#tO,58yPOOO,58y,58yOOQP1G.l1G.lO.lQXO,5:sOOQO-E8V-E8VOOQS1G.g1G.gOOQP1G.n1G.nO)dQWO1G.nO)iQWO1G.nOOQP1G/V1G/VO.yQ`O1G/ZO/dQXO1G/_O/zQXO1G/aO0bQXO1G/bO0xQWO,59zO0}Q[O'#DOO1UQdO'#CoOOQP1G/Z1G/ZO${QdO1G/ZO1]QpO,59]OOQS,59_,59_O${QdO,59aO1eQWO1G/kOOQS,59c,59cO1jQ!bO,59eO1rQWO'#DhO1}QWO,5:TO2SQWO,5:ZO&]Q[O,5:VO&]Q[O'#E[O2[QWO,5;]O2gQWO,5:XO(^Q[O,5:[OOQS1G/x1G/xOOQS1G/z1G/zOOQS1G/|1G/|O2xQWO1G/|O2}QdO'#D|OOQS1G0P1G0POOQS1G0V1G0VOOQS1G0X1G0XO3YQtO1G/gOOQO,5:u,5:uO3pQ[O,5:uOOQO-E8X-E8XO3}QWO1G0vPOOO-E8R-E8RPOOO1G.e1G.eOOQP7+$Y7+$YOOQP7+$u7+$uO${QdO7+$uOOQS1G/f1G/fO4YQXO'#EoO4aQWO,59jO4fQtO'#EVO5ZQdO'#ElO5eQWO,59ZO5jQpO7+$uOOQS1G.w1G.wOOQS1G.{1G.{OOQS7+%V7+%VO5rQWO1G/PO${QdO1G/oOOQO1G/u1G/uOOQO1G/q1G/qO5wQWO,5:vOOQO-E8Y-E8YO6VQXO1G/vOOQS7+%h7+%hO6^QYO'#CsOOQO'#EO'#EOO6iQ`O'#D}OOQO'#D}'#D}O6tQWO'#E]O6|QdO,5:hOOQS,5:h,5:hO7XQtO'#EYO${QdO'#EYO8VQdO7+%ROOQO7+%R7+%ROOQO1G0a1G0aO8jQpO<T![;'S%^;'S;=`%o<%lO%^l;TUo`Oy%^z!Q%^!Q![;g![;'S%^;'S;=`%o<%lO%^l;nYo`#b[Oy%^z!Q%^!Q![;g![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^l[[o`#b[Oy%^z!O%^!O!P;g!P!Q%^!Q![>T![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^n?VSp^Oy%^z;'S%^;'S;=`%o<%lO%^l?hWjWOy%^z!O%^!O!P;O!P!Q%^!Q![>T![;'S%^;'S;=`%o<%lO%^n@VU#_QOy%^z!Q%^!Q![;g![;'S%^;'S;=`%o<%lO%^~@nTjWOy%^z{@}{;'S%^;'S;=`%o<%lO%^~AUSo`#X~Oy%^z;'S%^;'S;=`%o<%lO%^lAg[#b[Oy%^z!O%^!O!P;g!P!Q%^!Q![>T![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^bBbU]QOy%^z![%^![!]Bt!];'S%^;'S;=`%o<%lO%^bB{S^Qo`Oy%^z;'S%^;'S;=`%o<%lO%^nC^S!W^Oy%^z;'S%^;'S;=`%o<%lO%^dCoSzSOy%^z;'S%^;'S;=`%o<%lO%^bDQU|QOy%^z!`%^!`!aDd!a;'S%^;'S;=`%o<%lO%^bDkS|Qo`Oy%^z;'S%^;'S;=`%o<%lO%^bDzWOy%^z!c%^!c!}Ed!}#T%^#T#oEd#o;'S%^;'S;=`%o<%lO%^bEk[!YQo`Oy%^z}%^}!OEd!O!Q%^!Q![Ed![!c%^!c!}Ed!}#T%^#T#oEd#o;'S%^;'S;=`%o<%lO%^bFfSxQOy%^z;'S%^;'S;=`%o<%lO%^lFwSv[Oy%^z;'S%^;'S;=`%o<%lO%^bGWUOy%^z#b%^#b#cGj#c;'S%^;'S;=`%o<%lO%^bGoUo`Oy%^z#W%^#W#XHR#X;'S%^;'S;=`%o<%lO%^bHYS!`Qo`Oy%^z;'S%^;'S;=`%o<%lO%^bHiUOy%^z#f%^#f#gHR#g;'S%^;'S;=`%o<%lO%^fIQS!RUOy%^z;'S%^;'S;=`%o<%lO%^nIcS!Q^Oy%^z;'S%^;'S;=`%o<%lO%^fItU!PQOy%^z!_%^!_!`6y!`;'S%^;'S;=`%o<%lO%^`JZP;=`<%l$}\",\n tokenizers: [descendant, unitToken, identifiers, 1, 2, 3, 4, new LocalTokenGroup(\"m~RRYZ[z{a~~g~aO#Z~~dP!P!Qg~lO#[~~\", 28, 102)],\n topRules: {\"StyleSheet\":[0,4],\"Styles\":[1,84]},\n specialized: [{term: 97, get: (value) => spec_callee[value] || -1},{term: 56, get: (value) => spec_AtKeyword[value] || -1},{term: 98, get: (value) => spec_identifier[value] || -1}],\n tokenPrec: 1169\n});\n\nexport { parser };\n","import { parser } from '@lezer/css';\nimport { syntaxTree, LRLanguage, indentNodeProp, continuedIndent, foldNodeProp, foldInside, LanguageSupport } from '@codemirror/language';\nimport { NodeWeakMap, IterMode } from '@lezer/common';\n\nlet _properties = null;\nfunction properties() {\n if (!_properties && typeof document == \"object\" && document.body) {\n let { style } = document.body, names = [], seen = new Set;\n for (let prop in style)\n if (prop != \"cssText\" && prop != \"cssFloat\") {\n if (typeof style[prop] == \"string\") {\n if (/[A-Z]/.test(prop))\n prop = prop.replace(/[A-Z]/g, ch => \"-\" + ch.toLowerCase());\n if (!seen.has(prop)) {\n names.push(prop);\n seen.add(prop);\n }\n }\n }\n _properties = names.sort().map(name => ({ type: \"property\", label: name }));\n }\n return _properties || [];\n}\nconst pseudoClasses = /*@__PURE__*/[\n \"active\", \"after\", \"any-link\", \"autofill\", \"backdrop\", \"before\",\n \"checked\", \"cue\", \"default\", \"defined\", \"disabled\", \"empty\",\n \"enabled\", \"file-selector-button\", \"first\", \"first-child\",\n \"first-letter\", \"first-line\", \"first-of-type\", \"focus\",\n \"focus-visible\", \"focus-within\", \"fullscreen\", \"has\", \"host\",\n \"host-context\", \"hover\", \"in-range\", \"indeterminate\", \"invalid\",\n \"is\", \"lang\", \"last-child\", \"last-of-type\", \"left\", \"link\", \"marker\",\n \"modal\", \"not\", \"nth-child\", \"nth-last-child\", \"nth-last-of-type\",\n \"nth-of-type\", \"only-child\", \"only-of-type\", \"optional\", \"out-of-range\",\n \"part\", \"placeholder\", \"placeholder-shown\", \"read-only\", \"read-write\",\n \"required\", \"right\", \"root\", \"scope\", \"selection\", \"slotted\", \"target\",\n \"target-text\", \"valid\", \"visited\", \"where\"\n].map(name => ({ type: \"class\", label: name }));\nconst values = /*@__PURE__*/[\n \"above\", \"absolute\", \"activeborder\", \"additive\", \"activecaption\", \"after-white-space\",\n \"ahead\", \"alias\", \"all\", \"all-scroll\", \"alphabetic\", \"alternate\", \"always\",\n \"antialiased\", \"appworkspace\", \"asterisks\", \"attr\", \"auto\", \"auto-flow\", \"avoid\", \"avoid-column\",\n \"avoid-page\", \"avoid-region\", \"axis-pan\", \"background\", \"backwards\", \"baseline\", \"below\",\n \"bidi-override\", \"blink\", \"block\", \"block-axis\", \"bold\", \"bolder\", \"border\", \"border-box\",\n \"both\", \"bottom\", \"break\", \"break-all\", \"break-word\", \"bullets\", \"button\", \"button-bevel\",\n \"buttonface\", \"buttonhighlight\", \"buttonshadow\", \"buttontext\", \"calc\", \"capitalize\",\n \"caps-lock-indicator\", \"caption\", \"captiontext\", \"caret\", \"cell\", \"center\", \"checkbox\", \"circle\",\n \"cjk-decimal\", \"clear\", \"clip\", \"close-quote\", \"col-resize\", \"collapse\", \"color\", \"color-burn\",\n \"color-dodge\", \"column\", \"column-reverse\", \"compact\", \"condensed\", \"contain\", \"content\",\n \"contents\", \"content-box\", \"context-menu\", \"continuous\", \"copy\", \"counter\", \"counters\", \"cover\",\n \"crop\", \"cross\", \"crosshair\", \"currentcolor\", \"cursive\", \"cyclic\", \"darken\", \"dashed\", \"decimal\",\n \"decimal-leading-zero\", \"default\", \"default-button\", \"dense\", \"destination-atop\", \"destination-in\",\n \"destination-out\", \"destination-over\", \"difference\", \"disc\", \"discard\", \"disclosure-closed\",\n \"disclosure-open\", \"document\", \"dot-dash\", \"dot-dot-dash\", \"dotted\", \"double\", \"down\", \"e-resize\",\n \"ease\", \"ease-in\", \"ease-in-out\", \"ease-out\", \"element\", \"ellipse\", \"ellipsis\", \"embed\", \"end\",\n \"ethiopic-abegede-gez\", \"ethiopic-halehame-aa-er\", \"ethiopic-halehame-gez\", \"ew-resize\", \"exclusion\",\n \"expanded\", \"extends\", \"extra-condensed\", \"extra-expanded\", \"fantasy\", \"fast\", \"fill\", \"fill-box\",\n \"fixed\", \"flat\", \"flex\", \"flex-end\", \"flex-start\", \"footnotes\", \"forwards\", \"from\",\n \"geometricPrecision\", \"graytext\", \"grid\", \"groove\", \"hand\", \"hard-light\", \"help\", \"hidden\", \"hide\",\n \"higher\", \"highlight\", \"highlighttext\", \"horizontal\", \"hsl\", \"hsla\", \"hue\", \"icon\", \"ignore\",\n \"inactiveborder\", \"inactivecaption\", \"inactivecaptiontext\", \"infinite\", \"infobackground\", \"infotext\",\n \"inherit\", \"initial\", \"inline\", \"inline-axis\", \"inline-block\", \"inline-flex\", \"inline-grid\",\n \"inline-table\", \"inset\", \"inside\", \"intrinsic\", \"invert\", \"italic\", \"justify\", \"keep-all\",\n \"landscape\", \"large\", \"larger\", \"left\", \"level\", \"lighter\", \"lighten\", \"line-through\", \"linear\",\n \"linear-gradient\", \"lines\", \"list-item\", \"listbox\", \"listitem\", \"local\", \"logical\", \"loud\", \"lower\",\n \"lower-hexadecimal\", \"lower-latin\", \"lower-norwegian\", \"lowercase\", \"ltr\", \"luminosity\", \"manipulation\",\n \"match\", \"matrix\", \"matrix3d\", \"medium\", \"menu\", \"menutext\", \"message-box\", \"middle\", \"min-intrinsic\",\n \"mix\", \"monospace\", \"move\", \"multiple\", \"multiple_mask_images\", \"multiply\", \"n-resize\", \"narrower\",\n \"ne-resize\", \"nesw-resize\", \"no-close-quote\", \"no-drop\", \"no-open-quote\", \"no-repeat\", \"none\",\n \"normal\", \"not-allowed\", \"nowrap\", \"ns-resize\", \"numbers\", \"numeric\", \"nw-resize\", \"nwse-resize\",\n \"oblique\", \"opacity\", \"open-quote\", \"optimizeLegibility\", \"optimizeSpeed\", \"outset\", \"outside\",\n \"outside-shape\", \"overlay\", \"overline\", \"padding\", \"padding-box\", \"painted\", \"page\", \"paused\",\n \"perspective\", \"pinch-zoom\", \"plus-darker\", \"plus-lighter\", \"pointer\", \"polygon\", \"portrait\",\n \"pre\", \"pre-line\", \"pre-wrap\", \"preserve-3d\", \"progress\", \"push-button\", \"radial-gradient\", \"radio\",\n \"read-only\", \"read-write\", \"read-write-plaintext-only\", \"rectangle\", \"region\", \"relative\", \"repeat\",\n \"repeating-linear-gradient\", \"repeating-radial-gradient\", \"repeat-x\", \"repeat-y\", \"reset\", \"reverse\",\n \"rgb\", \"rgba\", \"ridge\", \"right\", \"rotate\", \"rotate3d\", \"rotateX\", \"rotateY\", \"rotateZ\", \"round\",\n \"row\", \"row-resize\", \"row-reverse\", \"rtl\", \"run-in\", \"running\", \"s-resize\", \"sans-serif\", \"saturation\",\n \"scale\", \"scale3d\", \"scaleX\", \"scaleY\", \"scaleZ\", \"screen\", \"scroll\", \"scrollbar\", \"scroll-position\",\n \"se-resize\", \"self-start\", \"self-end\", \"semi-condensed\", \"semi-expanded\", \"separate\", \"serif\", \"show\",\n \"single\", \"skew\", \"skewX\", \"skewY\", \"skip-white-space\", \"slide\", \"slider-horizontal\",\n \"slider-vertical\", \"sliderthumb-horizontal\", \"sliderthumb-vertical\", \"slow\", \"small\", \"small-caps\",\n \"small-caption\", \"smaller\", \"soft-light\", \"solid\", \"source-atop\", \"source-in\", \"source-out\",\n \"source-over\", \"space\", \"space-around\", \"space-between\", \"space-evenly\", \"spell-out\", \"square\", \"start\",\n \"static\", \"status-bar\", \"stretch\", \"stroke\", \"stroke-box\", \"sub\", \"subpixel-antialiased\", \"svg_masks\",\n \"super\", \"sw-resize\", \"symbolic\", \"symbols\", \"system-ui\", \"table\", \"table-caption\", \"table-cell\",\n \"table-column\", \"table-column-group\", \"table-footer-group\", \"table-header-group\", \"table-row\",\n \"table-row-group\", \"text\", \"text-bottom\", \"text-top\", \"textarea\", \"textfield\", \"thick\", \"thin\",\n \"threeddarkshadow\", \"threedface\", \"threedhighlight\", \"threedlightshadow\", \"threedshadow\", \"to\", \"top\",\n \"transform\", \"translate\", \"translate3d\", \"translateX\", \"translateY\", \"translateZ\", \"transparent\",\n \"ultra-condensed\", \"ultra-expanded\", \"underline\", \"unidirectional-pan\", \"unset\", \"up\", \"upper-latin\",\n \"uppercase\", \"url\", \"var\", \"vertical\", \"vertical-text\", \"view-box\", \"visible\", \"visibleFill\",\n \"visiblePainted\", \"visibleStroke\", \"visual\", \"w-resize\", \"wait\", \"wave\", \"wider\", \"window\", \"windowframe\",\n \"windowtext\", \"words\", \"wrap\", \"wrap-reverse\", \"x-large\", \"x-small\", \"xor\", \"xx-large\", \"xx-small\"\n].map(name => ({ type: \"keyword\", label: name })).concat(/*@__PURE__*/[\n \"aliceblue\", \"antiquewhite\", \"aqua\", \"aquamarine\", \"azure\", \"beige\",\n \"bisque\", \"black\", \"blanchedalmond\", \"blue\", \"blueviolet\", \"brown\",\n \"burlywood\", \"cadetblue\", \"chartreuse\", \"chocolate\", \"coral\", \"cornflowerblue\",\n \"cornsilk\", \"crimson\", \"cyan\", \"darkblue\", \"darkcyan\", \"darkgoldenrod\",\n \"darkgray\", \"darkgreen\", \"darkkhaki\", \"darkmagenta\", \"darkolivegreen\",\n \"darkorange\", \"darkorchid\", \"darkred\", \"darksalmon\", \"darkseagreen\",\n \"darkslateblue\", \"darkslategray\", \"darkturquoise\", \"darkviolet\",\n \"deeppink\", \"deepskyblue\", \"dimgray\", \"dodgerblue\", \"firebrick\",\n \"floralwhite\", \"forestgreen\", \"fuchsia\", \"gainsboro\", \"ghostwhite\",\n \"gold\", \"goldenrod\", \"gray\", \"grey\", \"green\", \"greenyellow\", \"honeydew\",\n \"hotpink\", \"indianred\", \"indigo\", \"ivory\", \"khaki\", \"lavender\",\n \"lavenderblush\", \"lawngreen\", \"lemonchiffon\", \"lightblue\", \"lightcoral\",\n \"lightcyan\", \"lightgoldenrodyellow\", \"lightgray\", \"lightgreen\", \"lightpink\",\n \"lightsalmon\", \"lightseagreen\", \"lightskyblue\", \"lightslategray\",\n \"lightsteelblue\", \"lightyellow\", \"lime\", \"limegreen\", \"linen\", \"magenta\",\n \"maroon\", \"mediumaquamarine\", \"mediumblue\", \"mediumorchid\", \"mediumpurple\",\n \"mediumseagreen\", \"mediumslateblue\", \"mediumspringgreen\", \"mediumturquoise\",\n \"mediumvioletred\", \"midnightblue\", \"mintcream\", \"mistyrose\", \"moccasin\",\n \"navajowhite\", \"navy\", \"oldlace\", \"olive\", \"olivedrab\", \"orange\", \"orangered\",\n \"orchid\", \"palegoldenrod\", \"palegreen\", \"paleturquoise\", \"palevioletred\",\n \"papayawhip\", \"peachpuff\", \"peru\", \"pink\", \"plum\", \"powderblue\",\n \"purple\", \"rebeccapurple\", \"red\", \"rosybrown\", \"royalblue\", \"saddlebrown\",\n \"salmon\", \"sandybrown\", \"seagreen\", \"seashell\", \"sienna\", \"silver\", \"skyblue\",\n \"slateblue\", \"slategray\", \"snow\", \"springgreen\", \"steelblue\", \"tan\",\n \"teal\", \"thistle\", \"tomato\", \"turquoise\", \"violet\", \"wheat\", \"white\",\n \"whitesmoke\", \"yellow\", \"yellowgreen\"\n].map(name => ({ type: \"constant\", label: name })));\nconst tags = /*@__PURE__*/[\n \"a\", \"abbr\", \"address\", \"article\", \"aside\", \"b\", \"bdi\", \"bdo\", \"blockquote\", \"body\",\n \"br\", \"button\", \"canvas\", \"caption\", \"cite\", \"code\", \"col\", \"colgroup\", \"dd\", \"del\",\n \"details\", \"dfn\", \"dialog\", \"div\", \"dl\", \"dt\", \"em\", \"figcaption\", \"figure\", \"footer\",\n \"form\", \"header\", \"hgroup\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\", \"hr\", \"html\", \"i\", \"iframe\",\n \"img\", \"input\", \"ins\", \"kbd\", \"label\", \"legend\", \"li\", \"main\", \"meter\", \"nav\", \"ol\", \"output\",\n \"p\", \"pre\", \"ruby\", \"section\", \"select\", \"small\", \"source\", \"span\", \"strong\", \"sub\", \"summary\",\n \"sup\", \"table\", \"tbody\", \"td\", \"template\", \"textarea\", \"tfoot\", \"th\", \"thead\", \"tr\", \"u\", \"ul\"\n].map(name => ({ type: \"type\", label: name }));\nconst identifier = /^(\\w[\\w-]*|-\\w[\\w-]*|)$/, variable = /^-(-[\\w-]*)?$/;\nfunction isVarArg(node, doc) {\n var _a;\n if (node.name == \"(\" || node.type.isError)\n node = node.parent || node;\n if (node.name != \"ArgList\")\n return false;\n let callee = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.firstChild;\n if ((callee === null || callee === void 0 ? void 0 : callee.name) != \"Callee\")\n return false;\n return doc.sliceString(callee.from, callee.to) == \"var\";\n}\nconst VariablesByNode = /*@__PURE__*/new NodeWeakMap();\nconst declSelector = [\"Declaration\"];\nfunction astTop(node) {\n for (let cur = node;;) {\n if (cur.type.isTop)\n return cur;\n if (!(cur = cur.parent))\n return node;\n }\n}\nfunction variableNames(doc, node, isVariable) {\n if (node.to - node.from > 4096) {\n let known = VariablesByNode.get(node);\n if (known)\n return known;\n let result = [], seen = new Set, cursor = node.cursor(IterMode.IncludeAnonymous);\n if (cursor.firstChild())\n do {\n for (let option of variableNames(doc, cursor.node, isVariable))\n if (!seen.has(option.label)) {\n seen.add(option.label);\n result.push(option);\n }\n } while (cursor.nextSibling());\n VariablesByNode.set(node, result);\n return result;\n }\n else {\n let result = [], seen = new Set;\n node.cursor().iterate(node => {\n var _a;\n if (isVariable(node) && node.matchContext(declSelector) && ((_a = node.node.nextSibling) === null || _a === void 0 ? void 0 : _a.name) == \":\") {\n let name = doc.sliceString(node.from, node.to);\n if (!seen.has(name)) {\n seen.add(name);\n result.push({ label: name, type: \"variable\" });\n }\n }\n });\n return result;\n }\n}\n/**\nCreate a completion source for a CSS dialect, providing a\npredicate for determining what kind of syntax node can act as a\ncompletable variable. This is used by language modes like Sass and\nLess to reuse this package's completion logic.\n*/\nconst defineCSSCompletionSource = (isVariable) => context => {\n let { state, pos } = context, node = syntaxTree(state).resolveInner(pos, -1);\n let isDash = node.type.isError && node.from == node.to - 1 && state.doc.sliceString(node.from, node.to) == \"-\";\n if (node.name == \"PropertyName\" ||\n (isDash || node.name == \"TagName\") && /^(Block|Styles)$/.test(node.resolve(node.to).name))\n return { from: node.from, options: properties(), validFor: identifier };\n if (node.name == \"ValueName\")\n return { from: node.from, options: values, validFor: identifier };\n if (node.name == \"PseudoClassName\")\n return { from: node.from, options: pseudoClasses, validFor: identifier };\n if (isVariable(node) || (context.explicit || isDash) && isVarArg(node, state.doc))\n return { from: isVariable(node) || isDash ? node.from : pos,\n options: variableNames(state.doc, astTop(node), isVariable),\n validFor: variable };\n if (node.name == \"TagName\") {\n for (let { parent } = node; parent; parent = parent.parent)\n if (parent.name == \"Block\")\n return { from: node.from, options: properties(), validFor: identifier };\n return { from: node.from, options: tags, validFor: identifier };\n }\n if (!context.explicit)\n return null;\n let above = node.resolve(pos), before = above.childBefore(pos);\n if (before && before.name == \":\" && above.name == \"PseudoClassSelector\")\n return { from: pos, options: pseudoClasses, validFor: identifier };\n if (before && before.name == \":\" && above.name == \"Declaration\" || above.name == \"ArgList\")\n return { from: pos, options: values, validFor: identifier };\n if (above.name == \"Block\" || above.name == \"Styles\")\n return { from: pos, options: properties(), validFor: identifier };\n return null;\n};\n/**\nCSS property, variable, and value keyword completion source.\n*/\nconst cssCompletionSource = /*@__PURE__*/defineCSSCompletionSource(n => n.name == \"VariableName\");\n\n/**\nA language provider based on the [Lezer CSS\nparser](https://github.com/lezer-parser/css), extended with\nhighlighting and indentation information.\n*/\nconst cssLanguage = /*@__PURE__*/LRLanguage.define({\n name: \"css\",\n parser: /*@__PURE__*/parser.configure({\n props: [\n /*@__PURE__*/indentNodeProp.add({\n Declaration: /*@__PURE__*/continuedIndent()\n }),\n /*@__PURE__*/foldNodeProp.add({\n \"Block KeyframeList\": foldInside\n })\n ]\n }),\n languageData: {\n commentTokens: { block: { open: \"/*\", close: \"*/\" } },\n indentOnInput: /^\\s*\\}$/,\n wordChars: \"-\"\n }\n});\n/**\nLanguage support for CSS.\n*/\nfunction css() {\n return new LanguageSupport(cssLanguage, cssLanguage.data.of({ autocomplete: cssCompletionSource }));\n}\n\nexport { css, cssCompletionSource, cssLanguage, defineCSSCompletionSource };\n"],"names":["space","isAlpha","ch","identifiers","input","stack","inside","dashes","i","next","advance","peek","acceptToken","canShift","descendant","includes","unitToken","cssHighlighting","NamespaceName","KeyframeName","KeyframeRangeName","TagName","ClassName","PseudoClassName","IdName","AttributeName","NumberLiteral","KeywordQuery","UnaryQueryOp","VariableName","Callee","Unit","MatchOp","BinOp","Important","Comment","ColorLiteral","spec_callee","__proto__","lang","dir","url","domain","regexp","selector","spec_AtKeyword","spec_identifier","not","only","parser","version","states","stateData","goto","nodeNames","maxTerm","nodeProps","propSources","skippedNodes","repeatNodeCount","tokenData","tokenizers","topRules","specialized","term","get","value","tokenPrec","_properties","properties","document","body","style","names","seen","Set","prop","test","replace","toLowerCase","has","push","add","sort","map","name","type","label","pseudoClasses","values","concat","tags","variable","VariablesByNode","declSelector","astTop","node","cur","isTop","parent","variableNames","doc","isVariable","to","from","known","result","cursor","firstChild","option","nextSibling","set","iterate","_a","matchContext","sliceString","defineCSSCompletionSource","context","state","pos","resolveInner","isDash","isError","resolve","options","validFor","explicit","callee","isVarArg","above","before","childBefore","cssCompletionSource","n","cssLanguage","configure","props","Declaration","languageData","commentTokens","block","open","close","indentOnInput","wordChars","css","data","of","autocomplete"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/432.index.js b/book/_build/html/_static/432.index.js
new file mode 100644
index 0000000..05150f6
--- /dev/null
+++ b/book/_build/html/_static/432.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[432],{90432:(E,T,I)=>{I.r(T),I.d(T,{cobol:()=>S});var N="string",R="atom";function A(E){for(var T={},I=E.split(" "),N=0;N >= "),D={digit:/\d/,digit_or_colon:/[\d:]/,hex:/[0-9a-f]/i,sign:/[+-]/,exponent:/e/i,keyword_char:/[^\s\(\[\;\)\]]/,symbol:/[\w*+\-]/};const S={name:"cobol",startState:function(){return{indentStack:null,indentation:0,mode:!1}},token:function(E,T){if(null==T.indentStack&&E.sol()&&(T.indentation=6),E.eatSpace())return null;var I=null;if("string"===T.mode){for(var A=!1;null!=(A=E.next());)if(('"'==A||"'"==A)&&!E.match(/['"]/,!1)){T.mode=!1;break}I=N}else{var S=E.next(),U=E.column();if(U>=0&&U<=5)I="def";else if(U>=72&&U<=79)E.skipToEnd(),I="header";else if("*"==S&&6==U)E.skipToEnd(),I="comment";else if('"'==S||"'"==S)T.mode="string",I=N;else if("'"!=S||D.digit_or_colon.test(E.peek()))if("."==S)I="link";else if(function(E,T){return"0"===E&&T.eat(/x/i)?(T.eatWhile(D.hex),!0):("+"!=E&&"-"!=E||!D.digit.test(T.peek())||(T.eat(D.sign),E=T.next()),!!D.digit.test(E)&&(T.eat(E),T.eatWhile(D.digit),"."==T.peek()&&(T.eat("."),T.eatWhile(D.digit)),T.eat(D.exponent)&&(T.eat(D.sign),T.eatWhile(D.digit)),!0))}(S,E))I="number";else{if(E.current().match(D.symbol))for(;U<71&&void 0!==E.eat(D.symbol);)U++;I=C&&C.propertyIsEnumerable(E.current().toUpperCase())?"keyword":L&&L.propertyIsEnumerable(E.current().toUpperCase())?"builtin":O&&O.propertyIsEnumerable(E.current().toUpperCase())?R:null}else I=R}return I},indent:function(E){return null==E.indentStack?E.indentation:E.indentStack.indent}}}}]);
+//# sourceMappingURL=432.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/432.index.js.map b/book/_build/html/_static/432.index.js.map
new file mode 100644
index 0000000..ae06632
--- /dev/null
+++ b/book/_build/html/_static/432.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"432.index.js","mappings":"0HAAA,IAA8CA,EAAS,SACnDC,EAAO,OAEX,SAASC,EAAaC,GAEpB,IADA,IAAIC,EAAM,CAAC,EAAGC,EAAQF,EAAIG,MAAM,KACvBC,EAAI,EAAGA,EAAIF,EAAMG,SAAUD,EAAGH,EAAIC,EAAME,KAAM,EACvD,OAAOH,CACT,CACA,IAAIK,EAAQP,EAAa,mEACrBQ,EAAWR,EACb,48IA+GES,EAAWT,EAAa,2BACxBU,EAAQ,CACVC,MAAO,KACPC,eAAgB,QAChBC,IAAK,YACLC,KAAM,OACNC,SAAU,KACVC,aAAc,kBACdC,OAAQ,YA4BH,MAAMC,EAAQ,CACnBC,KAAM,QACNC,WAAY,WACV,MAAO,CACLC,YAAa,KACbC,YAAa,EACbC,MAAM,EAEV,EACAC,MAAO,SAAUC,EAAQC,GAMvB,GALyB,MAArBA,EAAML,aAAuBI,EAAOE,QAEtCD,EAAMJ,YAAc,GAGlBG,EAAOG,WACT,OAAO,KAET,IAAIC,EAAa,KACjB,GACK,WADEH,EAAMH,KACb,CAEE,IADA,IAAIO,GAAO,EACsB,OAAzBA,EAAOL,EAAOK,SACpB,IAAa,KAARA,GAAwB,KAARA,KAAkBL,EAAOM,MAAM,QAAQ,GAAQ,CAClEL,EAAMH,MAAO,EACb,KACF,CAEFM,EAAa/B,CACR,KACP,CACE,IAAIkC,EAAKP,EAAOK,OACZG,EAAMR,EAAOS,SACjB,GAAID,GAAO,GAAKA,GAAO,EACrBJ,EA7LW,WA8LN,GAAII,GAAO,IAAMA,GAAO,GAC7BR,EAAOU,YACPN,EAjM4D,cAkMvD,GAAU,KAANG,GAAoB,GAAPC,EACtBR,EAAOU,YACPN,EArM2B,eAsMtB,GAAU,KAANG,GAAoB,KAANA,EACvBN,EAAMH,KAAO,SACbM,EAAa/B,OACR,GAAU,KAANkC,GAAgBtB,EAAME,eAAewB,KAAKX,EAAOY,QAErD,GAAU,KAANL,EACTH,EA1M2B,YA2MtB,GA1Eb,SAAkBG,EAAIP,GAEpB,MAAY,MAAPO,GAAcP,EAAOa,IAAI,OAC5Bb,EAAOc,SAAS7B,EAAMG,MACf,IAGI,KAANmB,GAAmB,KAANA,IAAiBtB,EAAMC,MAAMyB,KAAKX,EAAOY,UAC3DZ,EAAOa,IAAI5B,EAAMI,MACjBkB,EAAKP,EAAOK,UAETpB,EAAMC,MAAMyB,KAAKJ,KACpBP,EAAOa,IAAIN,GACXP,EAAOc,SAAS7B,EAAMC,OACjB,KAAOc,EAAOY,SACjBZ,EAAOa,IAAI,KACXb,EAAOc,SAAS7B,EAAMC,QAEnBc,EAAOa,IAAI5B,EAAMK,YACpBU,EAAOa,IAAI5B,EAAMI,MACjBW,EAAOc,SAAS7B,EAAMC,SAEjB,GAGX,CAiDiB6B,CAASR,EAAGP,GACrBI,EA7MoB,aA8Mf,CACL,GAAIJ,EAAOgB,UAAUV,MAAMrB,EAAMO,QAC/B,KAAOgB,EAAM,SACsBS,IAA7BjB,EAAOa,IAAI5B,EAAMO,SAGnBgB,IAKJJ,EADErB,GAAYA,EAASmC,qBAAqBlB,EAAOgB,UAAUG,eAxNvB,UA0N7BnC,GAAYA,EAASkC,qBAAqBlB,EAAOgB,UAAUG,eA3NhE,UA6NKrC,GAASA,EAAMoC,qBAAqBlB,EAAOgB,UAAUG,eACjD7C,EACK,IACtB,MAtBE8B,EAAa9B,CAsBf,CAEF,OAAO8B,CACT,EACAgB,OAAQ,SAAUnB,GAChB,OAAyB,MAArBA,EAAML,YAA4BK,EAAMJ,YACrCI,EAAML,YAAYwB,MAC3B,E","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/cobol.js"],"sourcesContent":["var BUILTIN = \"builtin\", COMMENT = \"comment\", STRING = \"string\",\n ATOM = \"atom\", NUMBER = \"number\", KEYWORD = \"keyword\", MODTAG = \"header\",\n COBOLLINENUM = \"def\", PERIOD = \"link\";\nfunction makeKeywords(str) {\n var obj = {}, words = str.split(\" \");\n for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n return obj;\n}\nvar atoms = makeKeywords(\"TRUE FALSE ZEROES ZEROS ZERO SPACES SPACE LOW-VALUE LOW-VALUES \");\nvar keywords = makeKeywords(\n \"ACCEPT ACCESS ACQUIRE ADD ADDRESS \" +\n \"ADVANCING AFTER ALIAS ALL ALPHABET \" +\n \"ALPHABETIC ALPHABETIC-LOWER ALPHABETIC-UPPER ALPHANUMERIC ALPHANUMERIC-EDITED \" +\n \"ALSO ALTER ALTERNATE AND ANY \" +\n \"ARE AREA AREAS ARITHMETIC ASCENDING \" +\n \"ASSIGN AT ATTRIBUTE AUTHOR AUTO \" +\n \"AUTO-SKIP AUTOMATIC B-AND B-EXOR B-LESS \" +\n \"B-NOT B-OR BACKGROUND-COLOR BACKGROUND-COLOUR BEEP \" +\n \"BEFORE BELL BINARY BIT BITS \" +\n \"BLANK BLINK BLOCK BOOLEAN BOTTOM \" +\n \"BY CALL CANCEL CD CF \" +\n \"CH CHARACTER CHARACTERS CLASS CLOCK-UNITS \" +\n \"CLOSE COBOL CODE CODE-SET COL \" +\n \"COLLATING COLUMN COMMA COMMIT COMMITMENT \" +\n \"COMMON COMMUNICATION COMP COMP-0 COMP-1 \" +\n \"COMP-2 COMP-3 COMP-4 COMP-5 COMP-6 \" +\n \"COMP-7 COMP-8 COMP-9 COMPUTATIONAL COMPUTATIONAL-0 \" +\n \"COMPUTATIONAL-1 COMPUTATIONAL-2 COMPUTATIONAL-3 COMPUTATIONAL-4 COMPUTATIONAL-5 \" +\n \"COMPUTATIONAL-6 COMPUTATIONAL-7 COMPUTATIONAL-8 COMPUTATIONAL-9 COMPUTE \" +\n \"CONFIGURATION CONNECT CONSOLE CONTAINED CONTAINS \" +\n \"CONTENT CONTINUE CONTROL CONTROL-AREA CONTROLS \" +\n \"CONVERTING COPY CORR CORRESPONDING COUNT \" +\n \"CRT CRT-UNDER CURRENCY CURRENT CURSOR \" +\n \"DATA DATE DATE-COMPILED DATE-WRITTEN DAY \" +\n \"DAY-OF-WEEK DB DB-ACCESS-CONTROL-KEY DB-DATA-NAME DB-EXCEPTION \" +\n \"DB-FORMAT-NAME DB-RECORD-NAME DB-SET-NAME DB-STATUS DBCS \" +\n \"DBCS-EDITED DE DEBUG-CONTENTS DEBUG-ITEM DEBUG-LINE \" +\n \"DEBUG-NAME DEBUG-SUB-1 DEBUG-SUB-2 DEBUG-SUB-3 DEBUGGING \" +\n \"DECIMAL-POINT DECLARATIVES DEFAULT DELETE DELIMITED \" +\n \"DELIMITER DEPENDING DESCENDING DESCRIBED DESTINATION \" +\n \"DETAIL DISABLE DISCONNECT DISPLAY DISPLAY-1 \" +\n \"DISPLAY-2 DISPLAY-3 DISPLAY-4 DISPLAY-5 DISPLAY-6 \" +\n \"DISPLAY-7 DISPLAY-8 DISPLAY-9 DIVIDE DIVISION \" +\n \"DOWN DROP DUPLICATE DUPLICATES DYNAMIC \" +\n \"EBCDIC EGI EJECT ELSE EMI \" +\n \"EMPTY EMPTY-CHECK ENABLE END END. END-ACCEPT END-ACCEPT. \" +\n \"END-ADD END-CALL END-COMPUTE END-DELETE END-DISPLAY \" +\n \"END-DIVIDE END-EVALUATE END-IF END-INVOKE END-MULTIPLY \" +\n \"END-OF-PAGE END-PERFORM END-READ END-RECEIVE END-RETURN \" +\n \"END-REWRITE END-SEARCH END-START END-STRING END-SUBTRACT \" +\n \"END-UNSTRING END-WRITE END-XML ENTER ENTRY \" +\n \"ENVIRONMENT EOP EQUAL EQUALS ERASE \" +\n \"ERROR ESI EVALUATE EVERY EXCEEDS \" +\n \"EXCEPTION EXCLUSIVE EXIT EXTEND EXTERNAL \" +\n \"EXTERNALLY-DESCRIBED-KEY FD FETCH FILE FILE-CONTROL \" +\n \"FILE-STREAM FILES FILLER FINAL FIND \" +\n \"FINISH FIRST FOOTING FOR FOREGROUND-COLOR \" +\n \"FOREGROUND-COLOUR FORMAT FREE FROM FULL \" +\n \"FUNCTION GENERATE GET GIVING GLOBAL \" +\n \"GO GOBACK GREATER GROUP HEADING \" +\n \"HIGH-VALUE HIGH-VALUES HIGHLIGHT I-O I-O-CONTROL \" +\n \"ID IDENTIFICATION IF IN INDEX \" +\n \"INDEX-1 INDEX-2 INDEX-3 INDEX-4 INDEX-5 \" +\n \"INDEX-6 INDEX-7 INDEX-8 INDEX-9 INDEXED \" +\n \"INDIC INDICATE INDICATOR INDICATORS INITIAL \" +\n \"INITIALIZE INITIATE INPUT INPUT-OUTPUT INSPECT \" +\n \"INSTALLATION INTO INVALID INVOKE IS \" +\n \"JUST JUSTIFIED KANJI KEEP KEY \" +\n \"LABEL LAST LD LEADING LEFT \" +\n \"LEFT-JUSTIFY LENGTH LENGTH-CHECK LESS LIBRARY \" +\n \"LIKE LIMIT LIMITS LINAGE LINAGE-COUNTER \" +\n \"LINE LINE-COUNTER LINES LINKAGE LOCAL-STORAGE \" +\n \"LOCALE LOCALLY LOCK \" +\n \"MEMBER MEMORY MERGE MESSAGE METACLASS \" +\n \"MODE MODIFIED MODIFY MODULES MOVE \" +\n \"MULTIPLE MULTIPLY NATIONAL NATIVE NEGATIVE \" +\n \"NEXT NO NO-ECHO NONE NOT \" +\n \"NULL NULL-KEY-MAP NULL-MAP NULLS NUMBER \" +\n \"NUMERIC NUMERIC-EDITED OBJECT OBJECT-COMPUTER OCCURS \" +\n \"OF OFF OMITTED ON ONLY \" +\n \"OPEN OPTIONAL OR ORDER ORGANIZATION \" +\n \"OTHER OUTPUT OVERFLOW OWNER PACKED-DECIMAL \" +\n \"PADDING PAGE PAGE-COUNTER PARSE PERFORM \" +\n \"PF PH PIC PICTURE PLUS \" +\n \"POINTER POSITION POSITIVE PREFIX PRESENT \" +\n \"PRINTING PRIOR PROCEDURE PROCEDURE-POINTER PROCEDURES \" +\n \"PROCEED PROCESS PROCESSING PROGRAM PROGRAM-ID \" +\n \"PROMPT PROTECTED PURGE QUEUE QUOTE \" +\n \"QUOTES RANDOM RD READ READY \" +\n \"REALM RECEIVE RECONNECT RECORD RECORD-NAME \" +\n \"RECORDS RECURSIVE REDEFINES REEL REFERENCE \" +\n \"REFERENCE-MONITOR REFERENCES RELATION RELATIVE RELEASE \" +\n \"REMAINDER REMOVAL RENAMES REPEATED REPLACE \" +\n \"REPLACING REPORT REPORTING REPORTS REPOSITORY \" +\n \"REQUIRED RERUN RESERVE RESET RETAINING \" +\n \"RETRIEVAL RETURN RETURN-CODE RETURNING REVERSE-VIDEO \" +\n \"REVERSED REWIND REWRITE RF RH \" +\n \"RIGHT RIGHT-JUSTIFY ROLLBACK ROLLING ROUNDED \" +\n \"RUN SAME SCREEN SD SEARCH \" +\n \"SECTION SECURE SECURITY SEGMENT SEGMENT-LIMIT \" +\n \"SELECT SEND SENTENCE SEPARATE SEQUENCE \" +\n \"SEQUENTIAL SET SHARED SIGN SIZE \" +\n \"SKIP1 SKIP2 SKIP3 SORT SORT-MERGE \" +\n \"SORT-RETURN SOURCE SOURCE-COMPUTER SPACE-FILL \" +\n \"SPECIAL-NAMES STANDARD STANDARD-1 STANDARD-2 \" +\n \"START STARTING STATUS STOP STORE \" +\n \"STRING SUB-QUEUE-1 SUB-QUEUE-2 SUB-QUEUE-3 SUB-SCHEMA \" +\n \"SUBFILE SUBSTITUTE SUBTRACT SUM SUPPRESS \" +\n \"SYMBOLIC SYNC SYNCHRONIZED SYSIN SYSOUT \" +\n \"TABLE TALLYING TAPE TENANT TERMINAL \" +\n \"TERMINATE TEST TEXT THAN THEN \" +\n \"THROUGH THRU TIME TIMES TITLE \" +\n \"TO TOP TRAILING TRAILING-SIGN TRANSACTION \" +\n \"TYPE TYPEDEF UNDERLINE UNEQUAL UNIT \" +\n \"UNSTRING UNTIL UP UPDATE UPON \" +\n \"USAGE USAGE-MODE USE USING VALID \" +\n \"VALIDATE VALUE VALUES VARYING VLR \" +\n \"WAIT WHEN WHEN-COMPILED WITH WITHIN \" +\n \"WORDS WORKING-STORAGE WRITE XML XML-CODE \" +\n \"XML-EVENT XML-NTEXT XML-TEXT ZERO ZERO-FILL \" );\n\nvar builtins = makeKeywords(\"- * ** / + < <= = > >= \");\nvar tests = {\n digit: /\\d/,\n digit_or_colon: /[\\d:]/,\n hex: /[0-9a-f]/i,\n sign: /[+-]/,\n exponent: /e/i,\n keyword_char: /[^\\s\\(\\[\\;\\)\\]]/,\n symbol: /[\\w*+\\-]/\n};\nfunction isNumber(ch, stream){\n // hex\n if ( ch === '0' && stream.eat(/x/i) ) {\n stream.eatWhile(tests.hex);\n return true;\n }\n // leading sign\n if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) {\n stream.eat(tests.sign);\n ch = stream.next();\n }\n if ( tests.digit.test(ch) ) {\n stream.eat(ch);\n stream.eatWhile(tests.digit);\n if ( '.' == stream.peek()) {\n stream.eat('.');\n stream.eatWhile(tests.digit);\n }\n if ( stream.eat(tests.exponent) ) {\n stream.eat(tests.sign);\n stream.eatWhile(tests.digit);\n }\n return true;\n }\n return false;\n}\nexport const cobol = {\n name: \"cobol\",\n startState: function () {\n return {\n indentStack: null,\n indentation: 0,\n mode: false\n };\n },\n token: function (stream, state) {\n if (state.indentStack == null && stream.sol()) {\n // update indentation, but only if indentStack is empty\n state.indentation = 6 ; //stream.indentation();\n }\n // skip spaces\n if (stream.eatSpace()) {\n return null;\n }\n var returnType = null;\n switch(state.mode){\n case \"string\": // multi-line string parsing mode\n var next = false;\n while ((next = stream.next()) != null) {\n if ((next == \"\\\"\" || next == \"\\'\") && !stream.match(/['\"]/, false)) {\n state.mode = false;\n break;\n }\n }\n returnType = STRING; // continue on in string mode\n break;\n default: // default parsing mode\n var ch = stream.next();\n var col = stream.column();\n if (col >= 0 && col <= 5) {\n returnType = COBOLLINENUM;\n } else if (col >= 72 && col <= 79) {\n stream.skipToEnd();\n returnType = MODTAG;\n } else if (ch == \"*\" && col == 6) { // comment\n stream.skipToEnd(); // rest of the line is a comment\n returnType = COMMENT;\n } else if (ch == \"\\\"\" || ch == \"\\'\") {\n state.mode = \"string\";\n returnType = STRING;\n } else if (ch == \"'\" && !( tests.digit_or_colon.test(stream.peek()) )) {\n returnType = ATOM;\n } else if (ch == \".\") {\n returnType = PERIOD;\n } else if (isNumber(ch,stream)){\n returnType = NUMBER;\n } else {\n if (stream.current().match(tests.symbol)) {\n while (col < 71) {\n if (stream.eat(tests.symbol) === undefined) {\n break;\n } else {\n col++;\n }\n }\n }\n if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) {\n returnType = KEYWORD;\n } else if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase())) {\n returnType = BUILTIN;\n } else if (atoms && atoms.propertyIsEnumerable(stream.current().toUpperCase())) {\n returnType = ATOM;\n } else returnType = null;\n }\n }\n return returnType;\n },\n indent: function (state) {\n if (state.indentStack == null) return state.indentation;\n return state.indentStack.indent;\n }\n};\n\n"],"names":["STRING","ATOM","makeKeywords","str","obj","words","split","i","length","atoms","keywords","builtins","tests","digit","digit_or_colon","hex","sign","exponent","keyword_char","symbol","cobol","name","startState","indentStack","indentation","mode","token","stream","state","sol","eatSpace","returnType","next","match","ch","col","column","skipToEnd","test","peek","eat","eatWhile","isNumber","current","undefined","propertyIsEnumerable","toUpperCase","indent"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/4393.index.js b/book/_build/html/_static/4393.index.js
new file mode 100644
index 0000000..fe02fb5
--- /dev/null
+++ b/book/_build/html/_static/4393.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[4393],{84393:(e,t,i)=>{i.r(t),i.d(t,{properties:()=>n});const n={name:"properties",token:function(e,t){var i=e.sol()||t.afterSection,n=e.eol();if(t.afterSection=!1,i&&(t.nextMultiline?(t.inMultiline=!0,t.nextMultiline=!1):t.position="def"),n&&!t.nextMultiline&&(t.inMultiline=!1,t.position="def"),i)for(;e.eatSpace(););var o=e.next();return!i||"#"!==o&&"!"!==o&&";"!==o?i&&"["===o?(t.afterSection=!0,e.skipTo("]"),e.eat("]"),"header"):"="===o||":"===o?(t.position="quote",null):("\\"===o&&"quote"===t.position&&e.eol()&&(t.nextMultiline=!0),t.position):(t.position="comment",e.skipToEnd(),"comment")},startState:function(){return{position:"def",nextMultiline:!1,inMultiline:!1,afterSection:!1}}}}}]);
+//# sourceMappingURL=4393.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/4393.index.js.map b/book/_build/html/_static/4393.index.js.map
new file mode 100644
index 0000000..f217c59
--- /dev/null
+++ b/book/_build/html/_static/4393.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"4393.index.js","mappings":"gIAAO,MAAMA,EAAa,CACxBC,KAAM,aAENC,MAAO,SAASC,EAAQC,GACtB,IAAIC,EAAMF,EAAOE,OAASD,EAAME,aAC5BC,EAAMJ,EAAOI,MAkBjB,GAhBAH,EAAME,cAAe,EAEjBD,IACED,EAAMI,eACRJ,EAAMK,aAAc,EACpBL,EAAMI,eAAgB,GAEtBJ,EAAMM,SAAW,OAIjBH,IAASH,EAAMI,gBACjBJ,EAAMK,aAAc,EACpBL,EAAMM,SAAW,OAGfL,EACF,KAAMF,EAAOQ,aAGf,IAAIC,EAAKT,EAAOU,OAEhB,OAAIR,GAAe,MAAPO,GAAqB,MAAPA,GAAqB,MAAPA,EAI7BP,GAAc,MAAPO,GAChBR,EAAME,cAAe,EACrBH,EAAOW,OAAO,KAAMX,EAAOY,IAAI,KACxB,UACS,MAAPH,GAAqB,MAAPA,GACvBR,EAAMM,SAAW,QACV,OACS,OAAPE,GAAkC,UAAnBR,EAAMM,UAC1BP,EAAOI,QAETH,EAAMI,eAAgB,GAInBJ,EAAMM,WAjBXN,EAAMM,SAAW,UACjBP,EAAOa,YACA,UAgBX,EAEAC,WAAY,WACV,MAAO,CACLP,SAAW,MACXF,eAAgB,EAChBC,aAAc,EACdH,cAAe,EAEnB,E","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/properties.js"],"sourcesContent":["export const properties = {\n name: \"properties\",\n\n token: function(stream, state) {\n var sol = stream.sol() || state.afterSection;\n var eol = stream.eol();\n\n state.afterSection = false;\n\n if (sol) {\n if (state.nextMultiline) {\n state.inMultiline = true;\n state.nextMultiline = false;\n } else {\n state.position = \"def\";\n }\n }\n\n if (eol && ! state.nextMultiline) {\n state.inMultiline = false;\n state.position = \"def\";\n }\n\n if (sol) {\n while(stream.eatSpace()) {}\n }\n\n var ch = stream.next();\n\n if (sol && (ch === \"#\" || ch === \"!\" || ch === \";\")) {\n state.position = \"comment\";\n stream.skipToEnd();\n return \"comment\";\n } else if (sol && ch === \"[\") {\n state.afterSection = true;\n stream.skipTo(\"]\"); stream.eat(\"]\");\n return \"header\";\n } else if (ch === \"=\" || ch === \":\") {\n state.position = \"quote\";\n return null;\n } else if (ch === \"\\\\\" && state.position === \"quote\") {\n if (stream.eol()) { // end of line?\n // Multiline value\n state.nextMultiline = true;\n }\n }\n\n return state.position;\n },\n\n startState: function() {\n return {\n position : \"def\", // Current position, \"def\", \"quote\" or \"comment\"\n nextMultiline : false, // Is the next line multiline value\n inMultiline : false, // Is the current line a multiline value\n afterSection : false // Did we just open a section\n };\n }\n\n};\n"],"names":["properties","name","token","stream","state","sol","afterSection","eol","nextMultiline","inMultiline","position","eatSpace","ch","next","skipTo","eat","skipToEnd","startState"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/4537.index.js b/book/_build/html/_static/4537.index.js
new file mode 100644
index 0000000..42f4071
--- /dev/null
+++ b/book/_build/html/_static/4537.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[4537],{94537:(e,t,n)=>{function r(e,t){return new RegExp((t?"":"^")+"(?:"+e.join("|")+")"+(t?"$":"\\b"))}function a(e,t,n){return n.tokenize.push(e),e(t,n)}n.r(t),n.d(t,{crystal:()=>S});var u=/^(?:[-+/%|&^]|\*\*?|[<>]{2})/,i=/^(?:[=!]~|===|<=>|[<>=!]=?|[|&]{2}|~)/,c=/^(?:\[\][?=]?)/,o=/^(?:\.(?:\.{2})?|->|[?:])/,s=/^[a-z_\u009F-\uFFFF][a-zA-Z0-9_\u009F-\uFFFF]*/,l=/^[A-Z_\u009F-\uFFFF][a-zA-Z0-9_\u009F-\uFFFF]*/,f=r(["abstract","alias","as","asm","begin","break","case","class","def","do","else","elsif","end","ensure","enum","extend","for","fun","if","include","instance_sizeof","lib","macro","module","next","of","out","pointerof","private","protected","rescue","return","require","select","sizeof","struct","super","then","type","typeof","uninitialized","union","unless","until","when","while","with","yield","__DIR__","__END_LINE__","__FILE__","__LINE__"]),m=r(["true","false","nil","self"]),h=r(["def","fun","macro","class","module","struct","lib","enum","union","do","for"]),p=r(["if","unless","case","while","until","begin","then"]),k=["end","else","elsif","rescue","ensure"],d=r(k),F=["\\)","\\}","\\]"],z=new RegExp("^(?:"+F.join("|")+")$"),_={def:y,fun:y,macro:function(e,t){if(e.eatSpace())return null;var n;if(n=e.match(s)){if("def"==n)return"keyword";e.eat(/[?!]/)}return t.tokenize.pop(),"def"},class:I,module:I,struct:I,lib:I,enum:I,union:I},b={"[":"]","{":"}","(":")","<":">"};function g(e,t){if(e.eatSpace())return null;if("\\"!=t.lastToken&&e.match("{%",!1))return a(x("%","%"),e,t);if("\\"!=t.lastToken&&e.match("{{",!1))return a(x("{","}"),e,t);if("#"==e.peek())return e.skipToEnd(),"comment";var n;if(e.match(s))return e.eat(/[?!]/),n=e.current(),e.eat(":")?"atom":"."==t.lastToken?"property":f.test(n)?(h.test(n)?"fun"==n&&t.blocks.indexOf("lib")>=0||"def"==n&&"abstract"==t.lastToken||(t.blocks.push(n),t.currentIndent+=1):"operator"!=t.lastStyle&&t.lastStyle||!p.test(n)?"end"==n&&(t.blocks.pop(),t.currentIndent-=1):(t.blocks.push(n),t.currentIndent+=1),_.hasOwnProperty(n)&&t.tokenize.push(_[n]),"keyword"):m.test(n)?"atom":"variable";if(e.eat("@"))return"["==e.peek()?a(w("[","]","meta"),e,t):(e.eat("@"),e.match(s)||e.match(l),"propertyName");if(e.match(l))return"tag";if(e.eat(":"))return e.eat('"')?a(v('"',"atom",!1),e,t):e.match(s)||e.match(l)||e.match(u)||e.match(i)||e.match(c)?"atom":(e.eat(":"),"operator");if(e.eat('"'))return a(v('"',"string",!0),e,t);if("%"==e.peek()){var r,k="string",d=!0;if(e.match("%r"))k="string.special",r=e.next();else if(e.match("%w"))d=!1,r=e.next();else if(e.match("%q"))d=!1,r=e.next();else if(r=e.match(/^%([^\w\s=])/))r=r[1];else{if(e.match(/^%[a-zA-Z_\u009F-\uFFFF][\w\u009F-\uFFFF]*/))return"meta";if(e.eat("%"))return"operator"}return b.hasOwnProperty(r)&&(r=b[r]),a(v(r,k,d),e,t)}return(n=e.match(/^<<-('?)([A-Z]\w*)\1/))?a(function(e,t){return function(n,r){if(n.sol()&&(n.eatSpace(),n.match(e)))return r.tokenize.pop(),"string";for(var a=!1;n.peek();)if(a)n.next(),a=!1;else{if(n.match("{%",!1))return r.tokenize.push(x("%","%")),"string";if(n.match("{{",!1))return r.tokenize.push(x("{","}")),"string";if(t&&n.match("#{",!1))return r.tokenize.push(w("#{","}","meta")),"string";a=t&&"\\"==n.next()}return"string"}}(n[2],!n[1]),e,t):e.eat("'")?(e.match(/^(?:[^']|\\(?:[befnrtv0'"]|[0-7]{3}|u(?:[0-9a-fA-F]{4}|\{[0-9a-fA-F]{1,6}\})))/),e.eat("'"),"atom"):e.eat("0")?(e.eat("x")?e.match(/^[0-9a-fA-F_]+/):e.eat("o")?e.match(/^[0-7_]+/):e.eat("b")&&e.match(/^[01_]+/),"number"):e.eat(/^\d/)?(e.match(/^[\d_]*(?:\.[\d_]+)?(?:[eE][+-]?\d+)?/),"number"):e.match(u)?(e.eat("="),"operator"):e.match(i)||e.match(o)?"operator":(n=e.match(/[({[]/,!1))?a(w(n=n[0],b[n],null),e,t):e.eat("\\")?(e.next(),"meta"):(e.next(),null)}function w(e,t,n,r){return function(a,u){if(!r&&a.match(e))return u.tokenize[u.tokenize.length-1]=w(e,t,n,!0),u.currentIndent+=1,n;var i=g(a,u);return a.current()===t&&(u.tokenize.pop(),u.currentIndent-=1,i=n),i}}function x(e,t,n){return function(r,a){return!n&&r.match("{"+e)?(a.currentIndent+=1,a.tokenize[a.tokenize.length-1]=x(e,t,!0),"meta"):r.match(t+"}")?(a.currentIndent-=1,a.tokenize.pop(),"meta"):g(r,a)}}function y(e,t){return e.eatSpace()?null:(e.match(s)?e.eat(/[!?]/):e.match(u)||e.match(i)||e.match(c),t.tokenize.pop(),"def")}function I(e,t){return e.eatSpace()?null:(e.match(l),t.tokenize.pop(),"def")}function v(e,t,n){return function(r,a){for(var u=!1;r.peek();)if(u)r.next(),u=!1;else{if(r.match("{%",!1))return a.tokenize.push(x("%","%")),t;if(r.match("{{",!1))return a.tokenize.push(x("{","}")),t;if(n&&r.match("#{",!1))return a.tokenize.push(w("#{","}","meta")),t;var i=r.next();if(i==e)return a.tokenize.pop(),t;u=n&&"\\"==i}return t}}const S={name:"crystal",startState:function(){return{tokenize:[g],currentIndent:0,lastToken:null,lastStyle:null,blocks:[]}},token:function(e,t){var n=t.tokenize[t.tokenize.length-1](e,t),r=e.current();return n&&"comment"!=n&&(t.lastToken=r,t.lastStyle=n),n},indent:function(e,t,n){return t=t.replace(/^\s*(?:\{%)?\s*|\s*(?:%\})?\s*$/g,""),d.test(t)||z.test(t)?n.unit*(e.currentIndent-1):n.unit*e.currentIndent},languageData:{indentOnInput:r(F.concat(k),!0),commentTokens:{line:"#"}}}}}]);
+//# sourceMappingURL=4537.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/4537.index.js.map b/book/_build/html/_static/4537.index.js.map
new file mode 100644
index 0000000..73e570d
--- /dev/null
+++ b/book/_build/html/_static/4537.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"4537.index.js","mappings":"+FAAA,SAASA,EAAWC,EAAOC,GACzB,OAAO,IAAIC,QAAQD,EAAM,GAAK,KAAO,MAAQD,EAAMG,KAAK,KAAO,KAAOF,EAAM,IAAM,OACpF,CAEA,SAASG,EAAMC,EAAUC,EAAQC,GAE/B,OADAA,EAAMF,SAASG,KAAKH,GACbA,EAASC,EAAQC,EAC1B,C,8BAEA,IAAIE,EAAY,+BACZC,EAAuB,wCACvBC,EAAoB,iBACpBC,EAAmB,4BACnBC,EAAS,iDACTC,EAAQ,iDACRC,EAAWhB,EAAW,CACxB,WAAY,QAAS,KAAM,MAAO,QAAS,QAAS,OAAQ,QAAS,MAAO,KAC5E,OAAQ,QAAS,MAAO,SAAU,OAAQ,SAAU,MAAO,MAAO,KAClE,UAAW,kBAAmB,MAAO,QAAS,SAAU,OAAQ,KAAM,MAAO,YAC7E,UAAW,YAAa,SAAU,SAAU,UAAW,SAAU,SAAU,SAC3E,QAAS,OAAQ,OAAQ,SAAU,gBAAiB,QAAS,SAAU,QAAS,OAAQ,QAAS,OACjG,QAAS,UAAW,eAAgB,WAAY,aAE9CiB,EAAYjB,EAAW,CAAC,OAAQ,QAAS,MAAO,SAMhDkB,EAAiBlB,EALK,CACxB,MAAO,MAAO,QACd,QAAS,SAAU,SAAU,MAAO,OAAQ,QAC5C,KAAM,QAIJmB,EAA2BnB,EADK,CAAC,KAAM,SAAU,OAAQ,QAAS,QAAS,QAAS,SAEpFoB,EAAsB,CAAC,MAAO,OAAQ,QAAS,SAAU,UACzDC,EAAiBrB,EAAWoB,GAC5BE,EAAuB,CAAC,MAAO,MAAO,OACtCC,EAAkB,IAAIpB,OAAO,OAASmB,EAAqBlB,KAAK,KAAO,MACvEoB,EAAgB,CAClB,IAAOC,EAAkB,IAAOA,EAAkB,MA8NpD,SAAuBlB,EAAQC,GAC7B,GAAID,EAAOmB,WACT,OAAO,KAGT,IAAIC,EACJ,GAAIA,EAAUpB,EAAOqB,MAAMd,GAAS,CAClC,GAAe,OAAXa,EACF,MAAO,UAETpB,EAAOsB,IAAI,OACb,CAGA,OADArB,EAAMF,SAASwB,MACR,KACT,EA5OE,MAASC,EAAiB,OAAUA,EAAiB,OAAUA,EAC/D,IAAOA,EAAiB,KAAQA,EAAiB,MAASA,GAExDC,EAAW,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAEnD,SAASC,EAAU1B,EAAQC,GACzB,GAAID,EAAOmB,WACT,OAAO,KAIT,GAAuB,MAAnBlB,EAAM0B,WAAqB3B,EAAOqB,MAAM,MAAM,GAChD,OAAOvB,EAAM8B,EAAW,IAAK,KAAM5B,EAAQC,GAG7C,GAAuB,MAAnBA,EAAM0B,WAAqB3B,EAAOqB,MAAM,MAAM,GAChD,OAAOvB,EAAM8B,EAAW,IAAK,KAAM5B,EAAQC,GAI7C,GAAqB,KAAjBD,EAAO6B,OAET,OADA7B,EAAO8B,YACA,UAIT,IAAIV,EACJ,GAAIpB,EAAOqB,MAAMd,GAIf,OAHAP,EAAOsB,IAAI,QAEXF,EAAUpB,EAAO+B,UACb/B,EAAOsB,IAAI,KACN,OACqB,KAAnBrB,EAAM0B,UACR,WACElB,EAASuB,KAAKZ,IACnBT,EAAeqB,KAAKZ,GACL,OAAXA,GAAoBnB,EAAMgC,OAAOC,QAAQ,QAAU,GAAmB,OAAXd,GAAuC,YAAnBnB,EAAM0B,YACzF1B,EAAMgC,OAAO/B,KAAKkB,GAClBnB,EAAMkC,eAAiB,GAEI,YAAnBlC,EAAMmC,WAA4BnC,EAAMmC,YAAcxB,EAAyBoB,KAAKZ,GAG1E,OAAXA,IACTnB,EAAMgC,OAAOV,MACbtB,EAAMkC,eAAiB,IAJvBlC,EAAMgC,OAAO/B,KAAKkB,GAClBnB,EAAMkC,eAAiB,GAMrBlB,EAAcoB,eAAejB,IAC/BnB,EAAMF,SAASG,KAAKe,EAAcG,IAG7B,WACEV,EAAUsB,KAAKZ,GACjB,OAGF,WAKT,GAAIpB,EAAOsB,IAAI,KACb,MAAqB,KAAjBtB,EAAO6B,OACF/B,EAAMwC,EAAU,IAAK,IAAK,QAAStC,EAAQC,IAGpDD,EAAOsB,IAAI,KACXtB,EAAOqB,MAAMd,IAAWP,EAAOqB,MAAMb,GAC9B,gBAIT,GAAIR,EAAOqB,MAAMb,GACf,MAAO,MAIT,GAAIR,EAAOsB,IAAI,KACb,OAAItB,EAAOsB,IAAI,KACNxB,EAAMyC,EAAW,IAAM,QAAQ,GAAQvC,EAAQC,GAC7CD,EAAOqB,MAAMd,IAAWP,EAAOqB,MAAMb,IACrCR,EAAOqB,MAAMlB,IAAcH,EAAOqB,MAAMjB,IAAyBJ,EAAOqB,MAAMhB,GAChF,QAETL,EAAOsB,IAAI,KACJ,YAIT,GAAItB,EAAOsB,IAAI,KACb,OAAOxB,EAAMyC,EAAW,IAAM,UAAU,GAAOvC,EAAQC,GAIzD,GAAqB,KAAjBD,EAAO6B,OAAe,CACxB,IAEIW,EAFAC,EAAQ,SACRC,GAAQ,EAGZ,GAAI1C,EAAOqB,MAAM,MAEfoB,EAAQ,iBACRD,EAAQxC,EAAO2C,YACV,GAAI3C,EAAOqB,MAAM,MACtBqB,GAAQ,EACRF,EAAQxC,EAAO2C,YACV,GAAI3C,EAAOqB,MAAM,MACtBqB,GAAQ,EACRF,EAAQxC,EAAO2C,YAEf,GAAGH,EAAQxC,EAAOqB,MAAM,gBACtBmB,EAAQA,EAAM,OACT,IAAIxC,EAAOqB,MAAM,8CAEtB,MAAO,OACF,GAAIrB,EAAOsB,IAAI,KAEpB,MAAO,UACT,CAMF,OAHIG,EAASY,eAAeG,KAC1BA,EAAQf,EAASe,IAEZ1C,EAAMyC,EAAWC,EAAOC,EAAOC,GAAQ1C,EAAQC,EACxD,CAGA,OAAImB,EAAUpB,EAAOqB,MAAM,yBAClBvB,EA0KX,SAAsB8C,EAAQF,GAC5B,OAAO,SAAU1C,EAAQC,GACvB,GAAID,EAAO6C,QACT7C,EAAOmB,WACHnB,EAAOqB,MAAMuB,IAEf,OADA3C,EAAMF,SAASwB,MACR,SAKX,IADA,IAAIuB,GAAU,EACP9C,EAAO6B,QACZ,GAAKiB,EAkBH9C,EAAO2C,OACPG,GAAU,MAnBE,CACZ,GAAI9C,EAAOqB,MAAM,MAAM,GAErB,OADApB,EAAMF,SAASG,KAAK0B,EAAW,IAAK,MAC7B,SAGT,GAAI5B,EAAOqB,MAAM,MAAM,GAErB,OADApB,EAAMF,SAASG,KAAK0B,EAAW,IAAK,MAC7B,SAGT,GAAIc,GAAS1C,EAAOqB,MAAM,MAAM,GAE9B,OADApB,EAAMF,SAASG,KAAKoC,EAAU,KAAM,IAAK,SAClC,SAGTQ,EAAUJ,GAA0B,MAAjB1C,EAAO2C,MAC5B,CAMF,MAAO,QACT,CACF,CA/MiBI,CAAa3B,EAAQ,IAAKA,EAAQ,IAAKpB,EAAQC,GAI1DD,EAAOsB,IAAI,MACbtB,EAAOqB,MAAM,kFACbrB,EAAOsB,IAAI,KACJ,QAILtB,EAAOsB,IAAI,MACTtB,EAAOsB,IAAI,KACbtB,EAAOqB,MAAM,kBACJrB,EAAOsB,IAAI,KACpBtB,EAAOqB,MAAM,YACJrB,EAAOsB,IAAI,MACpBtB,EAAOqB,MAAM,WAER,UAGLrB,EAAOsB,IAAI,QACbtB,EAAOqB,MAAM,yCACN,UAILrB,EAAOqB,MAAMlB,IACfH,EAAOsB,IAAI,KACJ,YAGLtB,EAAOqB,MAAMjB,IAAyBJ,EAAOqB,MAAMf,GAC9C,YAILc,EAAUpB,EAAOqB,MAAM,SAAS,IAE3BvB,EAAMwC,EADblB,EAAUA,EAAQ,GACcK,EAASL,GAAU,MAAOpB,EAAQC,GAIhED,EAAOsB,IAAI,OACbtB,EAAO2C,OACA,SAGT3C,EAAO2C,OACA,KACT,CAEA,SAASL,EAAUU,EAAOrD,EAAK8C,EAAOQ,GACpC,OAAO,SAAUjD,EAAQC,GACvB,IAAKgD,GAAWjD,EAAOqB,MAAM2B,GAG3B,OAFA/C,EAAMF,SAASE,EAAMF,SAASmD,OAAS,GAAKZ,EAAUU,EAAOrD,EAAK8C,GAAO,GACzExC,EAAMkC,eAAiB,EAChBM,EAGT,IAAIU,EAAYzB,EAAU1B,EAAQC,GAOlC,OANID,EAAO+B,YAAcpC,IACvBM,EAAMF,SAASwB,MACftB,EAAMkC,eAAiB,EACvBgB,EAAYV,GAGPU,CACT,CACF,CAEA,SAASvB,EAAWoB,EAAOrD,EAAKsD,GAC9B,OAAO,SAAUjD,EAAQC,GACvB,OAAKgD,GAAWjD,EAAOqB,MAAM,IAAM2B,IACjC/C,EAAMkC,eAAiB,EACvBlC,EAAMF,SAASE,EAAMF,SAASmD,OAAS,GAAKtB,EAAWoB,EAAOrD,GAAK,GAC5D,QAGLK,EAAOqB,MAAM1B,EAAM,MACrBM,EAAMkC,eAAiB,EACvBlC,EAAMF,SAASwB,MACR,QAGFG,EAAU1B,EAAQC,EAC3B,CACF,CAmBA,SAASiB,EAAiBlB,EAAQC,GAChC,OAAID,EAAOmB,WACF,MAGLnB,EAAOqB,MAAMd,GACfP,EAAOsB,IAAI,QAEXtB,EAAOqB,MAAMlB,IAAcH,EAAOqB,MAAMjB,IAAyBJ,EAAOqB,MAAMhB,GAEhFJ,EAAMF,SAASwB,MACR,MACT,CAEA,SAASC,EAAgBxB,EAAQC,GAC/B,OAAID,EAAOmB,WACF,MAGTnB,EAAOqB,MAAMb,GACbP,EAAMF,SAASwB,MACR,MACT,CAEA,SAASgB,EAAW5C,EAAK8C,EAAOC,GAC9B,OAAO,SAAU1C,EAAQC,GAGvB,IAFA,IAAI6C,GAAU,EAEP9C,EAAO6B,QACZ,GAAKiB,EAyBH9C,EAAO2C,OACPG,GAAU,MA1BE,CACZ,GAAI9C,EAAOqB,MAAM,MAAM,GAErB,OADApB,EAAMF,SAASG,KAAK0B,EAAW,IAAK,MAC7Ba,EAGT,GAAIzC,EAAOqB,MAAM,MAAM,GAErB,OADApB,EAAMF,SAASG,KAAK0B,EAAW,IAAK,MAC7Ba,EAGT,GAAIC,GAAS1C,EAAOqB,MAAM,MAAM,GAE9B,OADApB,EAAMF,SAASG,KAAKoC,EAAU,KAAM,IAAK,SAClCG,EAGT,IAAIW,EAAKpD,EAAO2C,OAEhB,GAAIS,GAAMzD,EAER,OADAM,EAAMF,SAASwB,MACRkB,EAGTK,EAAUJ,GAAe,MAANU,CACrB,CAMF,OAAOX,CACT,CACF,CAyCO,MAAMY,EAAU,CACrBC,KAAM,UACNC,WAAY,WACV,MAAO,CACLxD,SAAU,CAAC2B,GACXS,cAAe,EACfR,UAAW,KACXS,UAAW,KACXH,OAAQ,GAEZ,EAEAuB,MAAO,SAAUxD,EAAQC,GACvB,IAAIwC,EAAQxC,EAAMF,SAASE,EAAMF,SAASmD,OAAS,GAAGlD,EAAQC,GAC1DuD,EAAQxD,EAAO+B,UAOnB,OALIU,GAAkB,WAATA,IACXxC,EAAM0B,UAAY6B,EAClBvD,EAAMmC,UAAYK,GAGbA,CACT,EAEAgB,OAAQ,SAAUxD,EAAOyD,EAAWC,GAGlC,OAFAD,EAAYA,EAAUE,QAAQ,mCAAoC,IAE9D9C,EAAekB,KAAK0B,IAAc1C,EAAgBgB,KAAK0B,GAClDC,EAAGE,MAAQ5D,EAAMkC,cAAgB,GAGnCwB,EAAGE,KAAO5D,EAAMkC,aACzB,EAEA2B,aAAc,CACZC,cAAetE,EAAWsB,EAAqBiD,OAAOnD,IAAsB,GAC5EoD,cAAe,CAACC,KAAM,M","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/crystal.js"],"sourcesContent":["function wordRegExp(words, end) {\n return new RegExp((end ? \"\" : \"^\") + \"(?:\" + words.join(\"|\") + \")\" + (end ? \"$\" : \"\\\\b\"));\n}\n\nfunction chain(tokenize, stream, state) {\n state.tokenize.push(tokenize);\n return tokenize(stream, state);\n}\n\nvar operators = /^(?:[-+/%|&^]|\\*\\*?|[<>]{2})/;\nvar conditionalOperators = /^(?:[=!]~|===|<=>|[<>=!]=?|[|&]{2}|~)/;\nvar indexingOperators = /^(?:\\[\\][?=]?)/;\nvar anotherOperators = /^(?:\\.(?:\\.{2})?|->|[?:])/;\nvar idents = /^[a-z_\\u009F-\\uFFFF][a-zA-Z0-9_\\u009F-\\uFFFF]*/;\nvar types = /^[A-Z_\\u009F-\\uFFFF][a-zA-Z0-9_\\u009F-\\uFFFF]*/;\nvar keywords = wordRegExp([\n \"abstract\", \"alias\", \"as\", \"asm\", \"begin\", \"break\", \"case\", \"class\", \"def\", \"do\",\n \"else\", \"elsif\", \"end\", \"ensure\", \"enum\", \"extend\", \"for\", \"fun\", \"if\",\n \"include\", \"instance_sizeof\", \"lib\", \"macro\", \"module\", \"next\", \"of\", \"out\", \"pointerof\",\n \"private\", \"protected\", \"rescue\", \"return\", \"require\", \"select\", \"sizeof\", \"struct\",\n \"super\", \"then\", \"type\", \"typeof\", \"uninitialized\", \"union\", \"unless\", \"until\", \"when\", \"while\", \"with\",\n \"yield\", \"__DIR__\", \"__END_LINE__\", \"__FILE__\", \"__LINE__\"\n]);\nvar atomWords = wordRegExp([\"true\", \"false\", \"nil\", \"self\"]);\nvar indentKeywordsArray = [\n \"def\", \"fun\", \"macro\",\n \"class\", \"module\", \"struct\", \"lib\", \"enum\", \"union\",\n \"do\", \"for\"\n];\nvar indentKeywords = wordRegExp(indentKeywordsArray);\nvar indentExpressionKeywordsArray = [\"if\", \"unless\", \"case\", \"while\", \"until\", \"begin\", \"then\"];\nvar indentExpressionKeywords = wordRegExp(indentExpressionKeywordsArray);\nvar dedentKeywordsArray = [\"end\", \"else\", \"elsif\", \"rescue\", \"ensure\"];\nvar dedentKeywords = wordRegExp(dedentKeywordsArray);\nvar dedentPunctualsArray = [\"\\\\)\", \"\\\\}\", \"\\\\]\"];\nvar dedentPunctuals = new RegExp(\"^(?:\" + dedentPunctualsArray.join(\"|\") + \")$\");\nvar nextTokenizer = {\n \"def\": tokenFollowIdent, \"fun\": tokenFollowIdent, \"macro\": tokenMacroDef,\n \"class\": tokenFollowType, \"module\": tokenFollowType, \"struct\": tokenFollowType,\n \"lib\": tokenFollowType, \"enum\": tokenFollowType, \"union\": tokenFollowType\n};\nvar matching = {\"[\": \"]\", \"{\": \"}\", \"(\": \")\", \"<\": \">\"};\n\nfunction tokenBase(stream, state) {\n if (stream.eatSpace()) {\n return null;\n }\n\n // Macros\n if (state.lastToken != \"\\\\\" && stream.match(\"{%\", false)) {\n return chain(tokenMacro(\"%\", \"%\"), stream, state);\n }\n\n if (state.lastToken != \"\\\\\" && stream.match(\"{{\", false)) {\n return chain(tokenMacro(\"{\", \"}\"), stream, state);\n }\n\n // Comments\n if (stream.peek() == \"#\") {\n stream.skipToEnd();\n return \"comment\";\n }\n\n // Variables and keywords\n var matched;\n if (stream.match(idents)) {\n stream.eat(/[?!]/);\n\n matched = stream.current();\n if (stream.eat(\":\")) {\n return \"atom\";\n } else if (state.lastToken == \".\") {\n return \"property\";\n } else if (keywords.test(matched)) {\n if (indentKeywords.test(matched)) {\n if (!(matched == \"fun\" && state.blocks.indexOf(\"lib\") >= 0) && !(matched == \"def\" && state.lastToken == \"abstract\")) {\n state.blocks.push(matched);\n state.currentIndent += 1;\n }\n } else if ((state.lastStyle == \"operator\" || !state.lastStyle) && indentExpressionKeywords.test(matched)) {\n state.blocks.push(matched);\n state.currentIndent += 1;\n } else if (matched == \"end\") {\n state.blocks.pop();\n state.currentIndent -= 1;\n }\n\n if (nextTokenizer.hasOwnProperty(matched)) {\n state.tokenize.push(nextTokenizer[matched]);\n }\n\n return \"keyword\";\n } else if (atomWords.test(matched)) {\n return \"atom\";\n }\n\n return \"variable\";\n }\n\n // Class variables and instance variables\n // or attributes\n if (stream.eat(\"@\")) {\n if (stream.peek() == \"[\") {\n return chain(tokenNest(\"[\", \"]\", \"meta\"), stream, state);\n }\n\n stream.eat(\"@\");\n stream.match(idents) || stream.match(types);\n return \"propertyName\";\n }\n\n // Constants and types\n if (stream.match(types)) {\n return \"tag\";\n }\n\n // Symbols or ':' operator\n if (stream.eat(\":\")) {\n if (stream.eat(\"\\\"\")) {\n return chain(tokenQuote(\"\\\"\", \"atom\", false), stream, state);\n } else if (stream.match(idents) || stream.match(types) ||\n stream.match(operators) || stream.match(conditionalOperators) || stream.match(indexingOperators)) {\n return \"atom\";\n }\n stream.eat(\":\");\n return \"operator\";\n }\n\n // Strings\n if (stream.eat(\"\\\"\")) {\n return chain(tokenQuote(\"\\\"\", \"string\", true), stream, state);\n }\n\n // Strings or regexps or macro variables or '%' operator\n if (stream.peek() == \"%\") {\n var style = \"string\";\n var embed = true;\n var delim;\n\n if (stream.match(\"%r\")) {\n // Regexps\n style = \"string.special\";\n delim = stream.next();\n } else if (stream.match(\"%w\")) {\n embed = false;\n delim = stream.next();\n } else if (stream.match(\"%q\")) {\n embed = false;\n delim = stream.next();\n } else {\n if(delim = stream.match(/^%([^\\w\\s=])/)) {\n delim = delim[1];\n } else if (stream.match(/^%[a-zA-Z_\\u009F-\\uFFFF][\\w\\u009F-\\uFFFF]*/)) {\n // Macro variables\n return \"meta\";\n } else if (stream.eat('%')) {\n // '%' operator\n return \"operator\";\n }\n }\n\n if (matching.hasOwnProperty(delim)) {\n delim = matching[delim];\n }\n return chain(tokenQuote(delim, style, embed), stream, state);\n }\n\n // Here Docs\n if (matched = stream.match(/^<<-('?)([A-Z]\\w*)\\1/)) {\n return chain(tokenHereDoc(matched[2], !matched[1]), stream, state)\n }\n\n // Characters\n if (stream.eat(\"'\")) {\n stream.match(/^(?:[^']|\\\\(?:[befnrtv0'\"]|[0-7]{3}|u(?:[0-9a-fA-F]{4}|\\{[0-9a-fA-F]{1,6}\\})))/);\n stream.eat(\"'\");\n return \"atom\";\n }\n\n // Numbers\n if (stream.eat(\"0\")) {\n if (stream.eat(\"x\")) {\n stream.match(/^[0-9a-fA-F_]+/);\n } else if (stream.eat(\"o\")) {\n stream.match(/^[0-7_]+/);\n } else if (stream.eat(\"b\")) {\n stream.match(/^[01_]+/);\n }\n return \"number\";\n }\n\n if (stream.eat(/^\\d/)) {\n stream.match(/^[\\d_]*(?:\\.[\\d_]+)?(?:[eE][+-]?\\d+)?/);\n return \"number\";\n }\n\n // Operators\n if (stream.match(operators)) {\n stream.eat(\"=\"); // Operators can follow assign symbol.\n return \"operator\";\n }\n\n if (stream.match(conditionalOperators) || stream.match(anotherOperators)) {\n return \"operator\";\n }\n\n // Parens and braces\n if (matched = stream.match(/[({[]/, false)) {\n matched = matched[0];\n return chain(tokenNest(matched, matching[matched], null), stream, state);\n }\n\n // Escapes\n if (stream.eat(\"\\\\\")) {\n stream.next();\n return \"meta\";\n }\n\n stream.next();\n return null;\n}\n\nfunction tokenNest(begin, end, style, started) {\n return function (stream, state) {\n if (!started && stream.match(begin)) {\n state.tokenize[state.tokenize.length - 1] = tokenNest(begin, end, style, true);\n state.currentIndent += 1;\n return style;\n }\n\n var nextStyle = tokenBase(stream, state);\n if (stream.current() === end) {\n state.tokenize.pop();\n state.currentIndent -= 1;\n nextStyle = style;\n }\n\n return nextStyle;\n };\n}\n\nfunction tokenMacro(begin, end, started) {\n return function (stream, state) {\n if (!started && stream.match(\"{\" + begin)) {\n state.currentIndent += 1;\n state.tokenize[state.tokenize.length - 1] = tokenMacro(begin, end, true);\n return \"meta\";\n }\n\n if (stream.match(end + \"}\")) {\n state.currentIndent -= 1;\n state.tokenize.pop();\n return \"meta\";\n }\n\n return tokenBase(stream, state);\n };\n}\n\nfunction tokenMacroDef(stream, state) {\n if (stream.eatSpace()) {\n return null;\n }\n\n var matched;\n if (matched = stream.match(idents)) {\n if (matched == \"def\") {\n return \"keyword\";\n }\n stream.eat(/[?!]/);\n }\n\n state.tokenize.pop();\n return \"def\";\n}\n\nfunction tokenFollowIdent(stream, state) {\n if (stream.eatSpace()) {\n return null;\n }\n\n if (stream.match(idents)) {\n stream.eat(/[!?]/);\n } else {\n stream.match(operators) || stream.match(conditionalOperators) || stream.match(indexingOperators);\n }\n state.tokenize.pop();\n return \"def\";\n}\n\nfunction tokenFollowType(stream, state) {\n if (stream.eatSpace()) {\n return null;\n }\n\n stream.match(types);\n state.tokenize.pop();\n return \"def\";\n}\n\nfunction tokenQuote(end, style, embed) {\n return function (stream, state) {\n var escaped = false;\n\n while (stream.peek()) {\n if (!escaped) {\n if (stream.match(\"{%\", false)) {\n state.tokenize.push(tokenMacro(\"%\", \"%\"));\n return style;\n }\n\n if (stream.match(\"{{\", false)) {\n state.tokenize.push(tokenMacro(\"{\", \"}\"));\n return style;\n }\n\n if (embed && stream.match(\"#{\", false)) {\n state.tokenize.push(tokenNest(\"#{\", \"}\", \"meta\"));\n return style;\n }\n\n var ch = stream.next();\n\n if (ch == end) {\n state.tokenize.pop();\n return style;\n }\n\n escaped = embed && ch == \"\\\\\";\n } else {\n stream.next();\n escaped = false;\n }\n }\n\n return style;\n };\n}\n\nfunction tokenHereDoc(phrase, embed) {\n return function (stream, state) {\n if (stream.sol()) {\n stream.eatSpace()\n if (stream.match(phrase)) {\n state.tokenize.pop();\n return \"string\";\n }\n }\n\n var escaped = false;\n while (stream.peek()) {\n if (!escaped) {\n if (stream.match(\"{%\", false)) {\n state.tokenize.push(tokenMacro(\"%\", \"%\"));\n return \"string\";\n }\n\n if (stream.match(\"{{\", false)) {\n state.tokenize.push(tokenMacro(\"{\", \"}\"));\n return \"string\";\n }\n\n if (embed && stream.match(\"#{\", false)) {\n state.tokenize.push(tokenNest(\"#{\", \"}\", \"meta\"));\n return \"string\";\n }\n\n escaped = embed && stream.next() == \"\\\\\";\n } else {\n stream.next();\n escaped = false;\n }\n }\n\n return \"string\";\n }\n}\n\nexport const crystal = {\n name: \"crystal\",\n startState: function () {\n return {\n tokenize: [tokenBase],\n currentIndent: 0,\n lastToken: null,\n lastStyle: null,\n blocks: []\n };\n },\n\n token: function (stream, state) {\n var style = state.tokenize[state.tokenize.length - 1](stream, state);\n var token = stream.current();\n\n if (style && style != \"comment\") {\n state.lastToken = token;\n state.lastStyle = style;\n }\n\n return style;\n },\n\n indent: function (state, textAfter, cx) {\n textAfter = textAfter.replace(/^\\s*(?:\\{%)?\\s*|\\s*(?:%\\})?\\s*$/g, \"\");\n\n if (dedentKeywords.test(textAfter) || dedentPunctuals.test(textAfter)) {\n return cx.unit * (state.currentIndent - 1);\n }\n\n return cx.unit * state.currentIndent;\n },\n\n languageData: {\n indentOnInput: wordRegExp(dedentPunctualsArray.concat(dedentKeywordsArray), true),\n commentTokens: {line: \"#\"}\n }\n};\n"],"names":["wordRegExp","words","end","RegExp","join","chain","tokenize","stream","state","push","operators","conditionalOperators","indexingOperators","anotherOperators","idents","types","keywords","atomWords","indentKeywords","indentExpressionKeywords","dedentKeywordsArray","dedentKeywords","dedentPunctualsArray","dedentPunctuals","nextTokenizer","tokenFollowIdent","eatSpace","matched","match","eat","pop","tokenFollowType","matching","tokenBase","lastToken","tokenMacro","peek","skipToEnd","current","test","blocks","indexOf","currentIndent","lastStyle","hasOwnProperty","tokenNest","tokenQuote","delim","style","embed","next","phrase","sol","escaped","tokenHereDoc","begin","started","length","nextStyle","ch","crystal","name","startState","token","indent","textAfter","cx","replace","unit","languageData","indentOnInput","concat","commentTokens","line"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/4651.index.js b/book/_build/html/_static/4651.index.js
new file mode 100644
index 0000000..efe94f0
--- /dev/null
+++ b/book/_build/html/_static/4651.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[4651],{54651:(t,e,n)=>{var r;function a(t){return new RegExp("^(?:"+t.join("|")+")$","i")}n.r(e),n.d(e,{sparql:()=>F});var u=a(["str","lang","langmatches","datatype","bound","sameterm","isiri","isuri","iri","uri","bnode","count","sum","min","max","avg","sample","group_concat","rand","abs","ceil","floor","round","concat","substr","strlen","replace","ucase","lcase","encode_for_uri","contains","strstarts","strends","strbefore","strafter","year","month","day","hours","minutes","seconds","timezone","tz","now","uuid","struuid","md5","sha1","sha256","sha384","sha512","coalesce","if","strlang","strdt","isnumeric","regex","exists","isblank","isliteral","a","bind"]),o=a(["base","prefix","select","distinct","reduced","construct","describe","ask","from","named","where","order","limit","offset","filter","optional","graph","by","asc","desc","as","having","undef","values","group","minus","in","not","service","silent","using","insert","delete","union","true","false","with","data","copy","to","move","add","create","drop","clear","load","into"]),i=/[*+\-<>=&|\^\/!\?]/,c="[A-Za-z_\\-0-9]",s=new RegExp("[A-Za-z]"),l=new RegExp("(("+c+"|\\.)*("+c+"))?:");function d(t,e){var n,a=t.next();if(r=null,"$"==a||"?"==a)return"?"==a&&t.match(/\s/,!1)?"operator":(t.match(/^[A-Za-z0-9_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][A-Za-z0-9_\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]*/),"variableName.local");if("<"==a&&!t.match(/^[\s\u00a0=]/,!1))return t.match(/^[^\s\u00a0>]*>?/),"atom";if('"'==a||"'"==a)return e.tokenize=(n=a,function(t,e){for(var r,a=!1;null!=(r=t.next());){if(r==n&&!a){e.tokenize=d;break}a=!a&&"\\"==r}return"string"}),e.tokenize(t,e);if(/[{}\(\),\.;\[\]]/.test(a))return r=a,"bracket";if("#"==a)return t.skipToEnd(),"comment";if(i.test(a))return"operator";if(":"==a)return f(t),"atom";if("@"==a)return t.eatWhile(/[a-z\d\-]/i),"meta";if(s.test(a)&&t.match(l))return f(t),"atom";t.eatWhile(/[_\w\d]/);var c=t.current();return u.test(c)?"builtin":o.test(c)?"keyword":"variable"}function f(t){t.match(/(\.(?=[\w_\-\\%])|[:\w_-]|\\[-\\_~.!$&'()*+,;=/?#@%]|%[a-f\d][a-f\d])+/i)}function p(t,e,n){t.context={prev:t.context,indent:t.indent,col:n,type:e}}function m(t){t.indent=t.context.indent,t.context=t.context.prev}const F={name:"sparql",startState:function(){return{tokenize:d,context:null,indent:0,col:0}},token:function(t,e){if(t.sol()&&(e.context&&null==e.context.align&&(e.context.align=!1),e.indent=t.indentation()),t.eatSpace())return null;var n=e.tokenize(t,e);if("comment"!=n&&e.context&&null==e.context.align&&"pattern"!=e.context.type&&(e.context.align=!0),"("==r)p(e,")",t.column());else if("["==r)p(e,"]",t.column());else if("{"==r)p(e,"}",t.column());else if(/[\]\}\)]/.test(r)){for(;e.context&&"pattern"==e.context.type;)m(e);e.context&&r==e.context.type&&(m(e),"}"==r&&e.context&&"pattern"==e.context.type&&m(e))}else"."==r&&e.context&&"pattern"==e.context.type?m(e):/atom|string|variable/.test(n)&&e.context&&(/[\}\]]/.test(e.context.type)?p(e,"pattern",t.column()):"pattern"!=e.context.type||e.context.align||(e.context.align=!0,e.context.col=t.column()));return n},indent:function(t,e,n){var r=e&&e.charAt(0),a=t.context;if(/[\]\}]/.test(r))for(;a&&"pattern"==a.type;)a=a.prev;var u=a&&r==a.type;return a?"pattern"==a.type?a.col:a.align?a.col+(u?0:1):a.indent+(u?0:n.unit):0},languageData:{commentTokens:{line:"#"}}}}}]);
+//# sourceMappingURL=4651.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/4651.index.js.map b/book/_build/html/_static/4651.index.js.map
new file mode 100644
index 0000000..31f823e
--- /dev/null
+++ b/book/_build/html/_static/4651.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"4651.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/sparql.js"],"sourcesContent":["var curPunc;\n\nfunction wordRegexp(words) {\n return new RegExp(\"^(?:\" + words.join(\"|\") + \")$\", \"i\");\n}\nvar ops = wordRegexp([\"str\", \"lang\", \"langmatches\", \"datatype\", \"bound\", \"sameterm\", \"isiri\", \"isuri\",\n \"iri\", \"uri\", \"bnode\", \"count\", \"sum\", \"min\", \"max\", \"avg\", \"sample\",\n \"group_concat\", \"rand\", \"abs\", \"ceil\", \"floor\", \"round\", \"concat\", \"substr\", \"strlen\",\n \"replace\", \"ucase\", \"lcase\", \"encode_for_uri\", \"contains\", \"strstarts\", \"strends\",\n \"strbefore\", \"strafter\", \"year\", \"month\", \"day\", \"hours\", \"minutes\", \"seconds\",\n \"timezone\", \"tz\", \"now\", \"uuid\", \"struuid\", \"md5\", \"sha1\", \"sha256\", \"sha384\",\n \"sha512\", \"coalesce\", \"if\", \"strlang\", \"strdt\", \"isnumeric\", \"regex\", \"exists\",\n \"isblank\", \"isliteral\", \"a\", \"bind\"]);\nvar keywords = wordRegexp([\"base\", \"prefix\", \"select\", \"distinct\", \"reduced\", \"construct\", \"describe\",\n \"ask\", \"from\", \"named\", \"where\", \"order\", \"limit\", \"offset\", \"filter\", \"optional\",\n \"graph\", \"by\", \"asc\", \"desc\", \"as\", \"having\", \"undef\", \"values\", \"group\",\n \"minus\", \"in\", \"not\", \"service\", \"silent\", \"using\", \"insert\", \"delete\", \"union\",\n \"true\", \"false\", \"with\",\n \"data\", \"copy\", \"to\", \"move\", \"add\", \"create\", \"drop\", \"clear\", \"load\", \"into\"]);\nvar operatorChars = /[*+\\-<>=&|\\^\\/!\\?]/;\nvar PN_CHARS = \"[A-Za-z_\\\\-0-9]\";\nvar PREFIX_START = new RegExp(\"[A-Za-z]\");\nvar PREFIX_REMAINDER = new RegExp(\"((\" + PN_CHARS + \"|\\\\.)*(\" + PN_CHARS + \"))?:\");\n\nfunction tokenBase(stream, state) {\n var ch = stream.next();\n curPunc = null;\n if (ch == \"$\" || ch == \"?\") {\n if(ch == \"?\" && stream.match(/\\s/, false)){\n return \"operator\";\n }\n stream.match(/^[A-Za-z0-9_\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][A-Za-z0-9_\\u00B7\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u203F-\\u2040\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD]*/);\n return \"variableName.local\";\n }\n else if (ch == \"<\" && !stream.match(/^[\\s\\u00a0=]/, false)) {\n stream.match(/^[^\\s\\u00a0>]*>?/);\n return \"atom\";\n }\n else if (ch == \"\\\"\" || ch == \"'\") {\n state.tokenize = tokenLiteral(ch);\n return state.tokenize(stream, state);\n }\n else if (/[{}\\(\\),\\.;\\[\\]]/.test(ch)) {\n curPunc = ch;\n return \"bracket\";\n }\n else if (ch == \"#\") {\n stream.skipToEnd();\n return \"comment\";\n }\n else if (operatorChars.test(ch)) {\n return \"operator\";\n }\n else if (ch == \":\") {\n eatPnLocal(stream);\n return \"atom\";\n }\n else if (ch == \"@\") {\n stream.eatWhile(/[a-z\\d\\-]/i);\n return \"meta\";\n }\n else if (PREFIX_START.test(ch) && stream.match(PREFIX_REMAINDER)) {\n eatPnLocal(stream);\n return \"atom\";\n }\n stream.eatWhile(/[_\\w\\d]/);\n var word = stream.current();\n if (ops.test(word))\n return \"builtin\";\n else if (keywords.test(word))\n return \"keyword\";\n else\n return \"variable\";\n}\n\nfunction eatPnLocal(stream) {\n stream.match(/(\\.(?=[\\w_\\-\\\\%])|[:\\w_-]|\\\\[-\\\\_~.!$&'()*+,;=/?#@%]|%[a-f\\d][a-f\\d])+/i);\n}\n\nfunction tokenLiteral(quote) {\n return function(stream, state) {\n var escaped = false, ch;\n while ((ch = stream.next()) != null) {\n if (ch == quote && !escaped) {\n state.tokenize = tokenBase;\n break;\n }\n escaped = !escaped && ch == \"\\\\\";\n }\n return \"string\";\n };\n}\n\nfunction pushContext(state, type, col) {\n state.context = {prev: state.context, indent: state.indent, col: col, type: type};\n}\nfunction popContext(state) {\n state.indent = state.context.indent;\n state.context = state.context.prev;\n}\n\nexport const sparql = {\n name: \"sparql\",\n\n startState: function() {\n return {tokenize: tokenBase,\n context: null,\n indent: 0,\n col: 0};\n },\n\n token: function(stream, state) {\n if (stream.sol()) {\n if (state.context && state.context.align == null) state.context.align = false;\n state.indent = stream.indentation();\n }\n if (stream.eatSpace()) return null;\n var style = state.tokenize(stream, state);\n\n if (style != \"comment\" && state.context && state.context.align == null && state.context.type != \"pattern\") {\n state.context.align = true;\n }\n\n if (curPunc == \"(\") pushContext(state, \")\", stream.column());\n else if (curPunc == \"[\") pushContext(state, \"]\", stream.column());\n else if (curPunc == \"{\") pushContext(state, \"}\", stream.column());\n else if (/[\\]\\}\\)]/.test(curPunc)) {\n while (state.context && state.context.type == \"pattern\") popContext(state);\n if (state.context && curPunc == state.context.type) {\n popContext(state);\n if (curPunc == \"}\" && state.context && state.context.type == \"pattern\")\n popContext(state);\n }\n }\n else if (curPunc == \".\" && state.context && state.context.type == \"pattern\") popContext(state);\n else if (/atom|string|variable/.test(style) && state.context) {\n if (/[\\}\\]]/.test(state.context.type))\n pushContext(state, \"pattern\", stream.column());\n else if (state.context.type == \"pattern\" && !state.context.align) {\n state.context.align = true;\n state.context.col = stream.column();\n }\n }\n\n return style;\n },\n\n indent: function(state, textAfter, cx) {\n var firstChar = textAfter && textAfter.charAt(0);\n var context = state.context;\n if (/[\\]\\}]/.test(firstChar))\n while (context && context.type == \"pattern\") context = context.prev;\n\n var closing = context && firstChar == context.type;\n if (!context)\n return 0;\n else if (context.type == \"pattern\")\n return context.col;\n else if (context.align)\n return context.col + (closing ? 0 : 1);\n else\n return context.indent + (closing ? 0 : cx.unit);\n },\n\n languageData: {\n commentTokens: {line: \"#\"}\n }\n};\n\n"],"names":["curPunc","wordRegexp","words","RegExp","join","ops","keywords","operatorChars","PN_CHARS","PREFIX_START","PREFIX_REMAINDER","tokenBase","stream","state","quote","ch","next","match","tokenize","escaped","test","skipToEnd","eatPnLocal","eatWhile","word","current","pushContext","type","col","context","prev","indent","popContext","sparql","name","startState","token","sol","align","indentation","eatSpace","style","column","textAfter","cx","firstChar","charAt","closing","unit","languageData","commentTokens","line"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/4745.index.js b/book/_build/html/_static/4745.index.js
new file mode 100644
index 0000000..6e568fe
--- /dev/null
+++ b/book/_build/html/_static/4745.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[4745],{74745:(e,t,r)=>{function n(e){return new RegExp("^(("+e.join(")|(")+"))\\b")}r.r(t),r.d(t,{webIDL:()=>E});var a=["Clamp","Constructor","EnforceRange","Exposed","ImplicitThis","Global","PrimaryGlobal","LegacyArrayClass","LegacyUnenumerableNamedProperties","LenientThis","NamedConstructor","NewObject","NoInterfaceObject","OverrideBuiltins","PutForwards","Replaceable","SameObject","TreatNonObjectAsNull","TreatNullAs","EmptyString","Unforgeable","Unscopeable"],i=n(a),c=["unsigned","short","long","unrestricted","float","double","boolean","byte","octet","Promise","ArrayBuffer","DataView","Int8Array","Int16Array","Int32Array","Uint8Array","Uint16Array","Uint32Array","Uint8ClampedArray","Float32Array","Float64Array","ByteString","DOMString","USVString","sequence","object","RegExp","Error","DOMException","FrozenArray","any","void"],o=n(c),l=["attribute","callback","const","deleter","dictionary","enum","getter","implements","inherit","interface","iterable","legacycaller","maplike","partial","required","serializer","setlike","setter","static","stringifier","typedef","optional","readonly","or"],m=n(l),s=["true","false","Infinity","NaN","null"],u=n(s),f=n(["callback","dictionary","enum","interface"]),b=n(["typedef"]),d=/^[:<=>?]/,y=/^-?([1-9][0-9]*|0[Xx][0-9A-Fa-f]+|0[0-7]*)/,p=/^-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+)/,h=/^_?[A-Za-z][0-9A-Z_a-z-]*/,A=/^_?[A-Za-z][0-9A-Z_a-z-]*(?=\s*;)/,g=/^"[^"]*"/,k=/^\/\*.*?\*\//,D=/^\/\*.*/,C=/^.*?\*\//;const E={name:"webidl",startState:function(){return{inComment:!1,lastToken:"",startDef:!1,endDef:!1}},token:function(e,t){var r=function(e,t){if(e.eatSpace())return null;if(t.inComment)return e.match(C)?(t.inComment=!1,"comment"):(e.skipToEnd(),"comment");if(e.match("//"))return e.skipToEnd(),"comment";if(e.match(k))return"comment";if(e.match(D))return t.inComment=!0,"comment";if(e.match(/^-?[0-9\.]/,!1)&&(e.match(y)||e.match(p)))return"number";if(e.match(g))return"string";if(t.startDef&&e.match(h))return"def";if(t.endDef&&e.match(A))return t.endDef=!1,"def";if(e.match(m))return"keyword";if(e.match(o)){var r=t.lastToken,n=(e.match(/^\s*(.+?)\b/,!1)||[])[1];return":"===r||"implements"===r||"implements"===n||"="===n?"builtin":"type"}return e.match(i)?"builtin":e.match(u)?"atom":e.match(h)?"variable":e.match(d)?"operator":(e.next(),null)}(e,t);if(r){var n=e.current();t.lastToken=n,"keyword"===r?(t.startDef=f.test(n),t.endDef=t.endDef||b.test(n)):t.startDef=!1}return r},languageData:{autocomplete:a.concat(c).concat(l).concat(s)}}}}]);
+//# sourceMappingURL=4745.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/4745.index.js.map b/book/_build/html/_static/4745.index.js.map
new file mode 100644
index 0000000..fd584f1
--- /dev/null
+++ b/book/_build/html/_static/4745.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"4745.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/webidl.js"],"sourcesContent":["function wordRegexp(words) {\n return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\");\n};\n\nvar builtinArray = [\n \"Clamp\",\n \"Constructor\",\n \"EnforceRange\",\n \"Exposed\",\n \"ImplicitThis\",\n \"Global\", \"PrimaryGlobal\",\n \"LegacyArrayClass\",\n \"LegacyUnenumerableNamedProperties\",\n \"LenientThis\",\n \"NamedConstructor\",\n \"NewObject\",\n \"NoInterfaceObject\",\n \"OverrideBuiltins\",\n \"PutForwards\",\n \"Replaceable\",\n \"SameObject\",\n \"TreatNonObjectAsNull\",\n \"TreatNullAs\",\n \"EmptyString\",\n \"Unforgeable\",\n \"Unscopeable\"\n];\nvar builtins = wordRegexp(builtinArray);\n\nvar typeArray = [\n \"unsigned\", \"short\", \"long\", // UnsignedIntegerType\n \"unrestricted\", \"float\", \"double\", // UnrestrictedFloatType\n \"boolean\", \"byte\", \"octet\", // Rest of PrimitiveType\n \"Promise\", // PromiseType\n \"ArrayBuffer\", \"DataView\", \"Int8Array\", \"Int16Array\", \"Int32Array\",\n \"Uint8Array\", \"Uint16Array\", \"Uint32Array\", \"Uint8ClampedArray\",\n \"Float32Array\", \"Float64Array\", // BufferRelatedType\n \"ByteString\", \"DOMString\", \"USVString\", \"sequence\", \"object\", \"RegExp\",\n \"Error\", \"DOMException\", \"FrozenArray\", // Rest of NonAnyType\n \"any\", // Rest of SingleType\n \"void\" // Rest of ReturnType\n];\nvar types = wordRegexp(typeArray);\n\nvar keywordArray = [\n \"attribute\", \"callback\", \"const\", \"deleter\", \"dictionary\", \"enum\", \"getter\",\n \"implements\", \"inherit\", \"interface\", \"iterable\", \"legacycaller\", \"maplike\",\n \"partial\", \"required\", \"serializer\", \"setlike\", \"setter\", \"static\",\n \"stringifier\", \"typedef\", // ArgumentNameKeyword except\n // \"unrestricted\"\n \"optional\", \"readonly\", \"or\"\n];\nvar keywords = wordRegexp(keywordArray);\n\nvar atomArray = [\n \"true\", \"false\", // BooleanLiteral\n \"Infinity\", \"NaN\", // FloatLiteral\n \"null\" // Rest of ConstValue\n];\nvar atoms = wordRegexp(atomArray);\n\nvar startDefArray = [\"callback\", \"dictionary\", \"enum\", \"interface\"];\nvar startDefs = wordRegexp(startDefArray);\n\nvar endDefArray = [\"typedef\"];\nvar endDefs = wordRegexp(endDefArray);\n\nvar singleOperators = /^[:<=>?]/;\nvar integers = /^-?([1-9][0-9]*|0[Xx][0-9A-Fa-f]+|0[0-7]*)/;\nvar floats = /^-?(([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+)/;\nvar identifiers = /^_?[A-Za-z][0-9A-Z_a-z-]*/;\nvar identifiersEnd = /^_?[A-Za-z][0-9A-Z_a-z-]*(?=\\s*;)/;\nvar strings = /^\"[^\"]*\"/;\nvar multilineComments = /^\\/\\*.*?\\*\\//;\nvar multilineCommentsStart = /^\\/\\*.*/;\nvar multilineCommentsEnd = /^.*?\\*\\//;\n\nfunction readToken(stream, state) {\n // whitespace\n if (stream.eatSpace()) return null;\n\n // comment\n if (state.inComment) {\n if (stream.match(multilineCommentsEnd)) {\n state.inComment = false;\n return \"comment\";\n }\n stream.skipToEnd();\n return \"comment\";\n }\n if (stream.match(\"//\")) {\n stream.skipToEnd();\n return \"comment\";\n }\n if (stream.match(multilineComments)) return \"comment\";\n if (stream.match(multilineCommentsStart)) {\n state.inComment = true;\n return \"comment\";\n }\n\n // integer and float\n if (stream.match(/^-?[0-9\\.]/, false)) {\n if (stream.match(integers) || stream.match(floats)) return \"number\";\n }\n\n // string\n if (stream.match(strings)) return \"string\";\n\n // identifier\n if (state.startDef && stream.match(identifiers)) return \"def\";\n\n if (state.endDef && stream.match(identifiersEnd)) {\n state.endDef = false;\n return \"def\";\n }\n\n if (stream.match(keywords)) return \"keyword\";\n\n if (stream.match(types)) {\n var lastToken = state.lastToken;\n var nextToken = (stream.match(/^\\s*(.+?)\\b/, false) || [])[1];\n\n if (lastToken === \":\" || lastToken === \"implements\" ||\n nextToken === \"implements\" || nextToken === \"=\") {\n // Used as identifier\n return \"builtin\";\n } else {\n // Used as type\n return \"type\";\n }\n }\n\n if (stream.match(builtins)) return \"builtin\";\n if (stream.match(atoms)) return \"atom\";\n if (stream.match(identifiers)) return \"variable\";\n\n // other\n if (stream.match(singleOperators)) return \"operator\";\n\n // unrecognized\n stream.next();\n return null;\n};\n\nexport const webIDL = {\n name: \"webidl\",\n startState: function() {\n return {\n // Is in multiline comment\n inComment: false,\n // Last non-whitespace, matched token\n lastToken: \"\",\n // Next token is a definition\n startDef: false,\n // Last token of the statement is a definition\n endDef: false\n };\n },\n token: function(stream, state) {\n var style = readToken(stream, state);\n\n if (style) {\n var cur = stream.current();\n state.lastToken = cur;\n if (style === \"keyword\") {\n state.startDef = startDefs.test(cur);\n state.endDef = state.endDef || endDefs.test(cur);\n } else {\n state.startDef = false;\n }\n }\n\n return style;\n },\n\n languageData: {\n autocomplete: builtinArray.concat(typeArray).concat(keywordArray).concat(atomArray)\n }\n};\n"],"names":["wordRegexp","words","RegExp","join","builtinArray","builtins","typeArray","types","keywordArray","keywords","atomArray","atoms","startDefs","endDefs","singleOperators","integers","floats","identifiers","identifiersEnd","strings","multilineComments","multilineCommentsStart","multilineCommentsEnd","webIDL","name","startState","inComment","lastToken","startDef","endDef","token","stream","state","style","eatSpace","match","skipToEnd","nextToken","next","readToken","cur","current","test","languageData","autocomplete","concat"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/4844.index.js b/book/_build/html/_static/4844.index.js
new file mode 100644
index 0000000..3ff4ff8
--- /dev/null
+++ b/book/_build/html/_static/4844.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[4844],{94844:(e,t,n)=>{function r(e){for(var t={},n=e.split(" "),r=0;rv});var a,o=r("abs acos allnodes ascii asin asstring atan atan2 ave case choose choosen choosesets clustersize combine correlation cos cosh count covariance cron dataset dedup define denormalize distribute distributed distribution ebcdic enth error evaluate event eventextra eventname exists exp failcode failmessage fetch fromunicode getisvalid global graph group hash hash32 hash64 hashcrc hashmd5 having if index intformat isvalid iterate join keyunicode length library limit ln local log loop map matched matchlength matchposition matchtext matchunicode max merge mergejoin min nolocal nonempty normalize parse pipe power preload process project pull random range rank ranked realformat recordof regexfind regexreplace regroup rejected rollup round roundup row rowdiff sample set sin sinh sizeof soapcall sort sorted sqrt stepped stored sum table tan tanh thisnode topn tounicode transfer trim truncate typeof ungroup unicodeorder variance which workunit xmldecode xmlencode xmltext xmlunicode"),i=r("apply assert build buildindex evaluate fail keydiff keypatch loadxml nothor notify output parallel sequential soapcall wait"),l=r("__compressed__ all and any as atmost before beginc++ best between case const counter csv descend encrypt end endc++ endmacro except exclusive expire export extend false few first flat from full function group header heading hole ifblock import in interface joined keep keyed last left limit load local locale lookup macro many maxcount maxlength min skew module named nocase noroot noscan nosort not of only opt or outer overwrite packed partition penalty physicallength pipe quote record relationship repeat return right scan self separator service shared skew skip sql store terminator thor threshold token transform trim true type unicodeorder unsorted validate virtual whole wild within xml xpath"),s=r("ascii big_endian boolean data decimal ebcdic integer pattern qstring real record rule set of string token udecimal unicode unsigned varstring varunicode"),u=r("checkpoint deprecated failcode failmessage failure global independent onwarning persist priority recovery stored success wait when"),c=r("catch class do else finally for if switch try while"),p=r("true false null"),d={"#":function(e,t){return!!t.startOfLine&&(e.skipToEnd(),"meta")}},m=/[+\-*&%=<>!?|\/]/;function f(e,t){var n,r=e.next();if(d[r]){var y=d[r](e,t);if(!1!==y)return y}if('"'==r||"'"==r)return t.tokenize=(n=r,function(e,t){for(var r,a=!1,o=!1;null!=(r=e.next());){if(r==n&&!a){o=!0;break}a=!a&&"\\"==r}return!o&&a||(t.tokenize=f),"string"}),t.tokenize(e,t);if(/[\[\]{}\(\),;\:\.]/.test(r))return a=r,null;if(/\d/.test(r))return e.eatWhile(/[\w\.]/),"number";if("/"==r){if(e.eat("*"))return t.tokenize=h,h(e,t);if(e.eat("/"))return e.skipToEnd(),"comment"}if(m.test(r))return e.eatWhile(m),"operator";e.eatWhile(/[\w\$_]/);var b=e.current().toLowerCase();if(o.propertyIsEnumerable(b))return c.propertyIsEnumerable(b)&&(a="newstatement"),"keyword";if(i.propertyIsEnumerable(b))return c.propertyIsEnumerable(b)&&(a="newstatement"),"variable";if(l.propertyIsEnumerable(b))return c.propertyIsEnumerable(b)&&(a="newstatement"),"modifier";if(s.propertyIsEnumerable(b))return c.propertyIsEnumerable(b)&&(a="newstatement"),"type";if(u.propertyIsEnumerable(b))return c.propertyIsEnumerable(b)&&(a="newstatement"),"builtin";for(var g=b.length-1;g>=0&&(!isNaN(b[g])||"_"==b[g]);)--g;if(g>0){var v=b.substr(0,g+1);if(s.propertyIsEnumerable(v))return c.propertyIsEnumerable(v)&&(a="newstatement"),"type"}return p.propertyIsEnumerable(b)?"atom":null}function h(e,t){for(var n,r=!1;n=e.next();){if("/"==n&&r){t.tokenize=f;break}r="*"==n}return"comment"}function y(e,t,n,r,a){this.indented=e,this.column=t,this.type=n,this.align=r,this.prev=a}function b(e,t,n){return e.context=new y(e.indented,t,n,null,e.context)}function g(e){var t=e.context.type;return")"!=t&&"]"!=t&&"}"!=t||(e.indented=e.context.indented),e.context=e.context.prev}const v={name:"ecl",startState:function(e){return{tokenize:null,context:new y(-e,0,"top",!1),indented:0,startOfLine:!0}},token:function(e,t){var n=t.context;if(e.sol()&&(null==n.align&&(n.align=!1),t.indented=e.indentation(),t.startOfLine=!0),e.eatSpace())return null;a=null;var r=(t.tokenize||f)(e,t);if("comment"==r||"meta"==r)return r;if(null==n.align&&(n.align=!0),";"!=a&&":"!=a||"statement"!=n.type)if("{"==a)b(t,e.column(),"}");else if("["==a)b(t,e.column(),"]");else if("("==a)b(t,e.column(),")");else if("}"==a){for(;"statement"==n.type;)n=g(t);for("}"==n.type&&(n=g(t));"statement"==n.type;)n=g(t)}else a==n.type?g(t):("}"==n.type||"top"==n.type||"statement"==n.type&&"newstatement"==a)&&b(t,e.column(),"statement");else g(t);return t.startOfLine=!1,r},indent:function(e,t,n){if(e.tokenize!=f&&null!=e.tokenize)return 0;var r=e.context,a=t&&t.charAt(0);"statement"==r.type&&"}"==a&&(r=r.prev);var o=a==r.type;return"statement"==r.type?r.indented+("{"==a?0:n.unit):r.align?r.column+(o?0:1):r.indented+(o?0:n.unit)},languageData:{indentOnInput:/^\s*[{}]$/}}}}]);
+//# sourceMappingURL=4844.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/4844.index.js.map b/book/_build/html/_static/4844.index.js.map
new file mode 100644
index 0000000..ff57b19
--- /dev/null
+++ b/book/_build/html/_static/4844.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"4844.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/ecl.js"],"sourcesContent":["function words(str) {\n var obj = {}, words = str.split(\" \");\n for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n return obj;\n}\n\nfunction metaHook(stream, state) {\n if (!state.startOfLine) return false;\n stream.skipToEnd();\n return \"meta\";\n}\n\nvar keyword = words(\"abs acos allnodes ascii asin asstring atan atan2 ave case choose choosen choosesets clustersize combine correlation cos cosh count covariance cron dataset dedup define denormalize distribute distributed distribution ebcdic enth error evaluate event eventextra eventname exists exp failcode failmessage fetch fromunicode getisvalid global graph group hash hash32 hash64 hashcrc hashmd5 having if index intformat isvalid iterate join keyunicode length library limit ln local log loop map matched matchlength matchposition matchtext matchunicode max merge mergejoin min nolocal nonempty normalize parse pipe power preload process project pull random range rank ranked realformat recordof regexfind regexreplace regroup rejected rollup round roundup row rowdiff sample set sin sinh sizeof soapcall sort sorted sqrt stepped stored sum table tan tanh thisnode topn tounicode transfer trim truncate typeof ungroup unicodeorder variance which workunit xmldecode xmlencode xmltext xmlunicode\");\nvar variable = words(\"apply assert build buildindex evaluate fail keydiff keypatch loadxml nothor notify output parallel sequential soapcall wait\");\nvar variable_2 = words(\"__compressed__ all and any as atmost before beginc++ best between case const counter csv descend encrypt end endc++ endmacro except exclusive expire export extend false few first flat from full function group header heading hole ifblock import in interface joined keep keyed last left limit load local locale lookup macro many maxcount maxlength min skew module named nocase noroot noscan nosort not of only opt or outer overwrite packed partition penalty physicallength pipe quote record relationship repeat return right scan self separator service shared skew skip sql store terminator thor threshold token transform trim true type unicodeorder unsorted validate virtual whole wild within xml xpath\");\nvar variable_3 = words(\"ascii big_endian boolean data decimal ebcdic integer pattern qstring real record rule set of string token udecimal unicode unsigned varstring varunicode\");\nvar builtin = words(\"checkpoint deprecated failcode failmessage failure global independent onwarning persist priority recovery stored success wait when\");\nvar blockKeywords = words(\"catch class do else finally for if switch try while\");\nvar atoms = words(\"true false null\");\nvar hooks = {\"#\": metaHook};\nvar isOperatorChar = /[+\\-*&%=<>!?|\\/]/;\n\nvar curPunc;\n\nfunction tokenBase(stream, state) {\n var ch = stream.next();\n if (hooks[ch]) {\n var result = hooks[ch](stream, state);\n if (result !== false) return result;\n }\n if (ch == '\"' || ch == \"'\") {\n state.tokenize = tokenString(ch);\n return state.tokenize(stream, state);\n }\n if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n curPunc = ch;\n return null;\n }\n if (/\\d/.test(ch)) {\n stream.eatWhile(/[\\w\\.]/);\n return \"number\";\n }\n if (ch == \"/\") {\n if (stream.eat(\"*\")) {\n state.tokenize = tokenComment;\n return tokenComment(stream, state);\n }\n if (stream.eat(\"/\")) {\n stream.skipToEnd();\n return \"comment\";\n }\n }\n if (isOperatorChar.test(ch)) {\n stream.eatWhile(isOperatorChar);\n return \"operator\";\n }\n stream.eatWhile(/[\\w\\$_]/);\n var cur = stream.current().toLowerCase();\n if (keyword.propertyIsEnumerable(cur)) {\n if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n return \"keyword\";\n } else if (variable.propertyIsEnumerable(cur)) {\n if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n return \"variable\";\n } else if (variable_2.propertyIsEnumerable(cur)) {\n if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n return \"modifier\";\n } else if (variable_3.propertyIsEnumerable(cur)) {\n if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n return \"type\";\n } else if (builtin.propertyIsEnumerable(cur)) {\n if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n return \"builtin\";\n } else { //Data types are of from KEYWORD##\n var i = cur.length - 1;\n while(i >= 0 && (!isNaN(cur[i]) || cur[i] == '_'))\n --i;\n\n if (i > 0) {\n var cur2 = cur.substr(0, i + 1);\n if (variable_3.propertyIsEnumerable(cur2)) {\n if (blockKeywords.propertyIsEnumerable(cur2)) curPunc = \"newstatement\";\n return \"type\";\n }\n }\n }\n if (atoms.propertyIsEnumerable(cur)) return \"atom\";\n return null;\n}\n\nfunction tokenString(quote) {\n return function(stream, state) {\n var escaped = false, next, end = false;\n while ((next = stream.next()) != null) {\n if (next == quote && !escaped) {end = true; break;}\n escaped = !escaped && next == \"\\\\\";\n }\n if (end || !escaped)\n state.tokenize = tokenBase;\n return \"string\";\n };\n}\n\nfunction tokenComment(stream, state) {\n var maybeEnd = false, ch;\n while (ch = stream.next()) {\n if (ch == \"/\" && maybeEnd) {\n state.tokenize = tokenBase;\n break;\n }\n maybeEnd = (ch == \"*\");\n }\n return \"comment\";\n}\n\nfunction Context(indented, column, type, align, prev) {\n this.indented = indented;\n this.column = column;\n this.type = type;\n this.align = align;\n this.prev = prev;\n}\nfunction pushContext(state, col, type) {\n return state.context = new Context(state.indented, col, type, null, state.context);\n}\nfunction popContext(state) {\n var t = state.context.type;\n if (t == \")\" || t == \"]\" || t == \"}\")\n state.indented = state.context.indented;\n return state.context = state.context.prev;\n}\n\n// Interface\n\nexport const ecl = {\n name: \"ecl\",\n startState: function(indentUnit) {\n return {\n tokenize: null,\n context: new Context(-indentUnit, 0, \"top\", false),\n indented: 0,\n startOfLine: true\n };\n },\n\n token: function(stream, state) {\n var ctx = state.context;\n if (stream.sol()) {\n if (ctx.align == null) ctx.align = false;\n state.indented = stream.indentation();\n state.startOfLine = true;\n }\n if (stream.eatSpace()) return null;\n curPunc = null;\n var style = (state.tokenize || tokenBase)(stream, state);\n if (style == \"comment\" || style == \"meta\") return style;\n if (ctx.align == null) ctx.align = true;\n\n if ((curPunc == \";\" || curPunc == \":\") && ctx.type == \"statement\") popContext(state);\n else if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n else if (curPunc == \"}\") {\n while (ctx.type == \"statement\") ctx = popContext(state);\n if (ctx.type == \"}\") ctx = popContext(state);\n while (ctx.type == \"statement\") ctx = popContext(state);\n }\n else if (curPunc == ctx.type) popContext(state);\n else if (ctx.type == \"}\" || ctx.type == \"top\" || (ctx.type == \"statement\" && curPunc == \"newstatement\"))\n pushContext(state, stream.column(), \"statement\");\n state.startOfLine = false;\n return style;\n },\n\n indent: function(state, textAfter, cx) {\n if (state.tokenize != tokenBase && state.tokenize != null) return 0;\n var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);\n if (ctx.type == \"statement\" && firstChar == \"}\") ctx = ctx.prev;\n var closing = firstChar == ctx.type;\n if (ctx.type == \"statement\") return ctx.indented + (firstChar == \"{\" ? 0 : cx.unit);\n else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n else return ctx.indented + (closing ? 0 : cx.unit);\n },\n\n languageData: {\n indentOnInput: /^\\s*[{}]$/\n }\n};\n"],"names":["words","str","obj","split","i","length","curPunc","keyword","variable","variable_2","variable_3","builtin","blockKeywords","atoms","hooks","stream","state","startOfLine","skipToEnd","isOperatorChar","tokenBase","quote","ch","next","result","tokenize","escaped","end","test","eatWhile","eat","tokenComment","cur","current","toLowerCase","propertyIsEnumerable","isNaN","cur2","substr","maybeEnd","Context","indented","column","type","align","prev","this","pushContext","col","context","popContext","t","ecl","name","startState","indentUnit","token","ctx","sol","indentation","eatSpace","style","indent","textAfter","cx","firstChar","charAt","closing","unit","languageData","indentOnInput"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/510.thebe-lite.min.js b/book/_build/html/_static/510.thebe-lite.min.js
new file mode 100644
index 0000000..87d2efb
--- /dev/null
+++ b/book/_build/html/_static/510.thebe-lite.min.js
@@ -0,0 +1,3 @@
+/*! For license information please see 510.thebe-lite.min.js.LICENSE.txt */
+(self.webpackChunkthebe_lite=self.webpackChunkthebe_lite||[]).push([[510],{144:(e,t,s)=>{"use strict";s.r(t),s.d(t,{PIPLITE_INDEX_SCHEMA:()=>N,PyodideKernel:()=>L,PyodideRemoteKernel:()=>z.O,allJSONUrl:()=>a,ipykernelWheelUrl:()=>r,pipliteWheelUrl:()=>l,pyodide_kernelWheelUrl:()=>c,widgetsnbextensionWheelUrl:()=>u,widgetsnbextensionWheelUrl1:()=>m});const n=s.p+"pypi/all.json";var a=s.t(n);const i=s.p+"pypi/ipykernel-6.9.2-py3-none-any.whl";var r=s.t(i);const o=s.p+"pypi/piplite-0.2.0-py3-none-any.whl";var l=s.t(o);const p=s.p+"pypi/pyodide_kernel-0.2.0-py3-none-any.whl";var c=s.t(p);const d=s.p+"pypi/widgetsnbextension-3.6.6-py3-none-any.whl";var u=s.t(d);const h=s.p+"pypi/widgetsnbextension-4.0.9-py3-none-any.whl";var m=s.t(h),y=s(5082),g=s(9622),_=s(6914),f=s(4016);class b{constructor(e){this._history=[],this._executionCount=0,this._isDisposed=!1,this._disposed=new f.Signal(this),this._parentHeader=void 0,this._parent=void 0;const{id:t,name:s,location:n,sendMessage:a}=e;this._id=t,this._name=s,this._location=n,this._sendMessage=a}get ready(){return Promise.resolve()}get isDisposed(){return this._isDisposed}get disposed(){return this._disposed}get id(){return this._id}get name(){return this._name}get location(){return this._location}get executionCount(){return this._executionCount}get parentHeader(){return this._parentHeader}get parent(){return this._parent}dispose(){this.isDisposed||(this._isDisposed=!0,this._disposed.emit(void 0))}async handleMessage(e){switch(this._busy(e),this._parent=e,e.header.msg_type){case"kernel_info_request":await this._kernelInfo(e);break;case"execute_request":await this._execute(e);break;case"input_reply":this.inputReply(e.content);break;case"inspect_request":await this._inspect(e);break;case"is_complete_request":await this._isCompleteRequest(e);break;case"complete_request":await this._complete(e);break;case"history_request":await this._historyRequest(e);break;case"comm_open":await this.commOpen(e);break;case"comm_msg":await this.commMsg(e);break;case"comm_close":await this.commClose(e)}this._idle(e)}stream(e,t=undefined){var s;const n=void 0!==t?t:this._parentHeader,a=_.KernelMessage.createMessage({channel:"iopub",msgType:"stream",session:null!==(s=null==n?void 0:n.session)&&void 0!==s?s:"",parentHeader:n,content:e});this._sendMessage(a)}displayData(e,t=undefined){var s,n;const a=void 0!==t?t:this._parentHeader;e.metadata=null!==(s=e.metadata)&&void 0!==s?s:{};const i=_.KernelMessage.createMessage({channel:"iopub",msgType:"display_data",session:null!==(n=null==a?void 0:a.session)&&void 0!==n?n:"",parentHeader:a,content:e});this._sendMessage(i)}inputRequest(e,t=undefined){var s;const n=void 0!==t?t:this._parentHeader,a=_.KernelMessage.createMessage({channel:"stdin",msgType:"input_request",session:null!==(s=null==n?void 0:n.session)&&void 0!==s?s:"",parentHeader:n,content:e});this._sendMessage(a)}publishExecuteResult(e,t=undefined){var s;const n=void 0!==t?t:this._parentHeader,a=_.KernelMessage.createMessage({channel:"iopub",msgType:"execute_result",session:null!==(s=null==n?void 0:n.session)&&void 0!==s?s:"",parentHeader:n,content:e});this._sendMessage(a)}publishExecuteError(e,t=undefined){var s;const n=void 0!==t?t:this._parentHeader,a=_.KernelMessage.createMessage({channel:"iopub",msgType:"error",session:null!==(s=null==n?void 0:n.session)&&void 0!==s?s:"",parentHeader:n,content:e});this._sendMessage(a)}updateDisplayData(e,t=undefined){var s;const n=void 0!==t?t:this._parentHeader,a=_.KernelMessage.createMessage({channel:"iopub",msgType:"update_display_data",session:null!==(s=null==n?void 0:n.session)&&void 0!==s?s:"",parentHeader:n,content:e});this._sendMessage(a)}clearOutput(e,t=undefined){var s;const n=void 0!==t?t:this._parentHeader,a=_.KernelMessage.createMessage({channel:"iopub",msgType:"clear_output",session:null!==(s=null==n?void 0:n.session)&&void 0!==s?s:"",parentHeader:n,content:e});this._sendMessage(a)}handleComm(e,t,s,n,a=undefined){var i;const r=void 0!==a?a:this._parentHeader,o=_.KernelMessage.createMessage({channel:"iopub",msgType:e,session:null!==(i=null==r?void 0:r.session)&&void 0!==i?i:"",parentHeader:r,content:t,metadata:s,buffers:n});this._sendMessage(o)}_idle(e){const t=_.KernelMessage.createMessage({msgType:"status",session:e.header.session,parentHeader:e.header,channel:"iopub",content:{execution_state:"idle"}});this._sendMessage(t)}_busy(e){const t=_.KernelMessage.createMessage({msgType:"status",session:e.header.session,parentHeader:e.header,channel:"iopub",content:{execution_state:"busy"}});this._sendMessage(t)}async _kernelInfo(e){const t=await this.kernelInfoRequest(),s=_.KernelMessage.createMessage({msgType:"kernel_info_reply",channel:"shell",session:e.header.session,parentHeader:e.header,content:t});this._sendMessage(s)}async _historyRequest(e){const t=e,s=_.KernelMessage.createMessage({msgType:"history_reply",channel:"shell",parentHeader:t.header,session:e.header.session,content:{status:"ok",history:this._history}});this._sendMessage(s)}_executeInput(e){const t=e,s=t.content.code,n=_.KernelMessage.createMessage({msgType:"execute_input",parentHeader:t.header,channel:"iopub",session:e.header.session,content:{code:s,execution_count:this._executionCount}});this._sendMessage(n)}async _execute(e){const t=e,s=t.content;s.store_history&&this._executionCount++,this._parentHeader=t.header,this._executeInput(t),s.store_history&&this._history.push([0,0,s.code]);const n=await this.executeRequest(t.content),a=_.KernelMessage.createMessage({msgType:"execute_reply",channel:"shell",parentHeader:t.header,session:e.header.session,content:n});this._sendMessage(a)}async _complete(e){const t=e,s=await this.completeRequest(t.content),n=_.KernelMessage.createMessage({msgType:"complete_reply",parentHeader:t.header,channel:"shell",session:e.header.session,content:s});this._sendMessage(n)}async _inspect(e){const t=e,s=await this.inspectRequest(t.content),n=_.KernelMessage.createMessage({msgType:"inspect_reply",parentHeader:t.header,channel:"shell",session:e.header.session,content:s});this._sendMessage(n)}async _isCompleteRequest(e){const t=e,s=await this.isCompleteRequest(t.content),n=_.KernelMessage.createMessage({msgType:"is_complete_reply",parentHeader:t.header,channel:"shell",session:e.header.session,content:s});this._sendMessage(n)}}const v=Symbol("Comlink.proxy"),w=Symbol("Comlink.endpoint"),M=Symbol("Comlink.releaseProxy"),k=Symbol("Comlink.finalizer"),x=Symbol("Comlink.thrown"),E=e=>"object"==typeof e&&null!==e||"function"==typeof e,H=new Map([["proxy",{canHandle:e=>E(e)&&e[v],serialize(e){const{port1:t,port2:s}=new MessageChannel;return R(e,t),[s,[s]]},deserialize:e=>(e.start(),C(e))}],["throw",{canHandle:e=>E(e)&&x in e,serialize({value:e}){let t;return t=e instanceof Error?{isError:!0,value:{message:e.message,name:e.name,stack:e.stack}}:{isError:!1,value:e},[t,[]]},deserialize(e){if(e.isError)throw Object.assign(new Error(e.value.message),e.value);throw e.value}}]]);function R(e,t=globalThis,s=["*"]){t.addEventListener("message",(function n(a){if(!a||!a.data)return;if(!function(e,t){for(const s of e){if(t===s||"*"===s)return!0;if(s instanceof RegExp&&s.test(t))return!0}return!1}(s,a.origin))return void console.warn(`Invalid origin '${a.origin}' for comlink proxy`);const{id:i,type:r,path:o}=Object.assign({path:[]},a.data),l=(a.data.argumentList||[]).map(I);let p;try{const t=o.slice(0,-1).reduce(((e,t)=>e[t]),e),s=o.reduce(((e,t)=>e[t]),e);switch(r){case"GET":p=s;break;case"SET":t[o.slice(-1)[0]]=I(a.data.value),p=!0;break;case"APPLY":p=s.apply(t,l);break;case"CONSTRUCT":p=function(e){return Object.assign(e,{[v]:!0})}(new s(...l));break;case"ENDPOINT":{const{port1:t,port2:s}=new MessageChannel;R(e,s),p=function(e,t){return U.set(e,t),e}(t,[t])}break;case"RELEASE":p=void 0;break;default:return}}catch(e){p={value:e,[x]:0}}Promise.resolve(p).catch((e=>({value:e,[x]:0}))).then((s=>{const[a,o]=j(s);t.postMessage(Object.assign(Object.assign({},a),{id:i}),o),"RELEASE"===r&&(t.removeEventListener("message",n),T(t),k in e&&"function"==typeof e[k]&&e[k]())})).catch((e=>{const[s,n]=j({value:new TypeError("Unserializable return value"),[x]:0});t.postMessage(Object.assign(Object.assign({},s),{id:i}),n)}))})),t.start&&t.start()}function T(e){(function(e){return"MessagePort"===e.constructor.name})(e)&&e.close()}function C(e,t){return S(e,[],t)}function K(e){if(e)throw new Error("Proxy has been released and is not useable")}function P(e){return A(e,{type:"RELEASE"}).then((()=>{T(e)}))}const O=new WeakMap,q="FinalizationRegistry"in globalThis&&new FinalizationRegistry((e=>{const t=(O.get(e)||0)-1;O.set(e,t),0===t&&P(e)}));function S(e,t=[],s=function(){}){let n=!1;const a=new Proxy(s,{get(s,i){if(K(n),i===M)return()=>{!function(e){q&&q.unregister(e)}(a),P(e),n=!0};if("then"===i){if(0===t.length)return{then:()=>a};const s=A(e,{type:"GET",path:t.map((e=>e.toString()))}).then(I);return s.then.bind(s)}return S(e,[...t,i])},set(s,a,i){K(n);const[r,o]=j(i);return A(e,{type:"SET",path:[...t,a].map((e=>e.toString())),value:r},o).then(I)},apply(s,a,i){K(n);const r=t[t.length-1];if(r===w)return A(e,{type:"ENDPOINT"}).then(I);if("bind"===r)return S(e,t.slice(0,-1));const[o,l]=D(i);return A(e,{type:"APPLY",path:t.map((e=>e.toString())),argumentList:o},l).then(I)},construct(s,a){K(n);const[i,r]=D(a);return A(e,{type:"CONSTRUCT",path:t.map((e=>e.toString())),argumentList:i},r).then(I)}});return function(e,t){const s=(O.get(t)||0)+1;O.set(t,s),q&&q.register(e,t,e)}(a,e),a}function D(e){const t=e.map(j);return[t.map((e=>e[0])),(s=t.map((e=>e[1])),Array.prototype.concat.apply([],s))];var s}const U=new WeakMap;function j(e){for(const[t,s]of H)if(s.canHandle(e)){const[n,a]=s.serialize(e);return[{type:"HANDLER",name:t,value:n},a]}return[{type:"RAW",value:e},U.get(e)||[]]}function I(e){switch(e.type){case"HANDLER":return H.get(e.name).deserialize(e.value);case"RAW":return e.value}}function A(e,t,s){return new Promise((n=>{const a=new Array(4).fill(0).map((()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16))).join("-");e.addEventListener("message",(function t(s){s.data&&s.data.id&&s.data.id===a&&(e.removeEventListener("message",t),n(s.data))})),e.start&&e.start(),e.postMessage(Object.assign({id:a},t),s)}))}class L extends b{constructor(e){super(e),this._ready=new y.PromiseDelegate,this._worker=this.initWorker(e),this._worker.onmessage=e=>this._processWorkerMessage(e.data),this._remoteKernel=C(this._worker),this.initRemote(e)}initWorker(e){return new Worker(new URL(s.p+s.u(946),s.b),{type:void 0})}async initRemote(e){const t=this.initRemoteOptions(e);await this._remoteKernel.initialize(t),this._ready.resolve()}initRemoteOptions(e){const{pyodideUrl:t}=e,s=t.slice(0,t.lastIndexOf("/")+1),a=g.PageConfig.getBaseUrl(),i=[...e.pipliteUrls||[],n],r=!!e.disablePyPIFallback;return{baseUrl:a,pyodideUrl:t,indexUrl:s,pipliteWheelUrl:e.pipliteWheelUrl||o,pipliteUrls:i,disablePyPIFallback:r,location:this.location,mountDrive:e.mountDrive}}dispose(){this.isDisposed||(this._worker.terminate(),this._worker=null,super.dispose())}get ready(){return this._ready.promise}_processWorkerMessage(e){var t,s,n,a,i,r,o;if(e.type)switch(e.type){case"stream":{const s=null!==(t=e.bundle)&&void 0!==t?t:{name:"stdout",text:""};this.stream(s,e.parentHeader);break}case"input_request":{const t=null!==(s=e.content)&&void 0!==s?s:{prompt:"",password:!1};this.inputRequest(t,e.parentHeader);break}case"display_data":{const t=null!==(n=e.bundle)&&void 0!==n?n:{data:{},metadata:{},transient:{}};this.displayData(t,e.parentHeader);break}case"update_display_data":{const t=null!==(a=e.bundle)&&void 0!==a?a:{data:{},metadata:{},transient:{}};this.updateDisplayData(t,e.parentHeader);break}case"clear_output":{const t=null!==(i=e.bundle)&&void 0!==i?i:{wait:!1};this.clearOutput(t,e.parentHeader);break}case"execute_result":{const t=null!==(r=e.bundle)&&void 0!==r?r:{execution_count:0,data:{},metadata:{}};this.publishExecuteResult(t,e.parentHeader);break}case"execute_error":{const t=null!==(o=e.bundle)&&void 0!==o?o:{ename:"",evalue:"",traceback:[]};this.publishExecuteError(t,e.parentHeader);break}case"comm_msg":case"comm_open":case"comm_close":this.handleComm(e.type,e.content,e.metadata,e.buffers,e.parentHeader)}}async kernelInfoRequest(){return{implementation:"pyodide",implementation_version:"0.1.0",language_info:{codemirror_mode:{name:"python",version:3},file_extension:".py",mimetype:"text/x-python",name:"python",nbconvert_exporter:"python",pygments_lexer:"ipython3",version:"3.8"},protocol_version:"5.3",status:"ok",banner:"A WebAssembly-powered Python kernel backed by Pyodide",help_links:[{text:"Python (WASM) Kernel",url:"https://pyodide.org"}]}}async executeRequest(e){await this.ready;const t=await this._remoteKernel.execute(e,this.parent);return t.execution_count=this.executionCount,t}async completeRequest(e){return await this._remoteKernel.complete(e,this.parent)}async inspectRequest(e){return await this._remoteKernel.inspect(e,this.parent)}async isCompleteRequest(e){return await this._remoteKernel.isComplete(e,this.parent)}async commInfoRequest(e){return await this._remoteKernel.commInfo(e,this.parent)}async commOpen(e){return await this._remoteKernel.commOpen(e,this.parent)}async commMsg(e){return await this._remoteKernel.commMsg(e,this.parent)}async commClose(e){return await this._remoteKernel.commClose(e,this.parent)}async inputReply(e){return await this._remoteKernel.inputReply(e,this.parent)}}const W=JSON.parse('{"$schema":"http://json-schema.org/draft-07/schema","$id":"https://jupyterlite-pyodide-kernel.readthedocs.org/en/latest/reference/schema/piplite-v0.html#","title":"PipLite Schema v0","description":"a schema for the warehouse-like API index","$ref":"#/definitions/top","definitions":{"top":{"type":"object","patternProperties":{".*":{"$ref":"#/definitions/a-piplite-project"}}},"a-piplite-project":{"type":"object","description":"a piplite-installable project, with one or more historical releases","properties":{"releases":{"patternProperties":{".*":{"type":"array","items":{"$ref":"#/definitions/a-piplite-distribution"}}}}}},"a-piplite-distribution":{"type":"object","properties":{"comment_text":{"type":"string"},"digests":{"type":"object","properties":{"md5":{"$ref":"#/definitions/an-md5-digest"},"sha256":{"$ref":"#/definitions/a-sha256-digest"}}},"downloads":{"type":"number"},"filename":{"type":"string"},"has_sig":{"type":"boolean"},"md5_digest":{"$ref":"#/definitions/an-md5-digest"},"packagetype":{"type":"string","enum":["bdist_wheel"]},"python_version":{"type":"string"},"requires_python":{"$ref":"#/definitions/string-or-null"},"size":{"type":"number"},"upload_time":{"type":"string","format":"date-time"},"upload_time_iso_8601":{"type":"string","format":"date-time"},"url":{"type":"string","format":"uri"},"yanked":{"type":"boolean"},"yanked_reason":{"$ref":"#/definitions/string-or-null"}}},"string-or-null":{"anyOf":[{"type":"string"},{"type":"null"}]},"an-md5-digest":{"type":"string","pattern":"[a-f0-9]{32}"},"a-sha256-digest":{"type":"string","pattern":"[a-f0-9]{64}"}}}');var N=s.t(W,2),z=s(3296)},265:e=>{function t(e){return Promise.resolve().then((()=>{var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}))}t.keys=()=>[],t.resolve=t,t.id=265,e.exports=t}}]);
+//# sourceMappingURL=510.thebe-lite.min.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/510.thebe-lite.min.js.LICENSE.txt b/book/_build/html/_static/510.thebe-lite.min.js.LICENSE.txt
new file mode 100644
index 0000000..479a8e5
--- /dev/null
+++ b/book/_build/html/_static/510.thebe-lite.min.js.LICENSE.txt
@@ -0,0 +1,5 @@
+/**
+ * @license
+ * Copyright 2019 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
diff --git a/book/_build/html/_static/510.thebe-lite.min.js.map b/book/_build/html/_static/510.thebe-lite.min.js.map
new file mode 100644
index 0000000..8846324
--- /dev/null
+++ b/book/_build/html/_static/510.thebe-lite.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"510.thebe-lite.min.js","mappings":"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","sources":["webpack://thebe-lite/./node_modules/@jupyterlite/kernel/lib/kernel.js","webpack://thebe-lite/../../node_modules/comlink/dist/esm/comlink.mjs","webpack://thebe-lite/./node_modules/@jupyterlite/pyodide-kernel/lib/kernel.js","webpack://thebe-lite/./node_modules/@jupyterlite/pyodide-kernel/lib/ lazy namespace object"],"sourcesContent":["import { KernelMessage } from '@jupyterlab/services';\nimport { Signal } from '@lumino/signaling';\n/**\n * A base kernel class handling basic kernel messaging.\n */\nexport class BaseKernel {\n /**\n * Construct a new BaseKernel.\n *\n * @param options The instantiation options for a BaseKernel.\n */\n constructor(options) {\n this._history = [];\n this._executionCount = 0;\n this._isDisposed = false;\n this._disposed = new Signal(this);\n this._parentHeader = undefined;\n this._parent = undefined;\n const { id, name, location, sendMessage } = options;\n this._id = id;\n this._name = name;\n this._location = location;\n this._sendMessage = sendMessage;\n }\n /**\n * A promise that is fulfilled when the kernel is ready.\n */\n get ready() {\n return Promise.resolve();\n }\n /**\n * Return whether the kernel is disposed.\n */\n get isDisposed() {\n return this._isDisposed;\n }\n /**\n * A signal emitted when the kernel is disposed.\n */\n get disposed() {\n return this._disposed;\n }\n /**\n * Get the kernel id\n */\n get id() {\n return this._id;\n }\n /**\n * Get the name of the kernel\n */\n get name() {\n return this._name;\n }\n /**\n * The location in the virtual filesystem from which the kernel was started.\n */\n get location() {\n return this._location;\n }\n /**\n * The current execution count\n */\n get executionCount() {\n return this._executionCount;\n }\n /**\n * Get the last parent header\n */\n get parentHeader() {\n return this._parentHeader;\n }\n /**\n * Get the last parent message (mimic ipykernel's get_parent)\n */\n get parent() {\n return this._parent;\n }\n /**\n * Dispose the kernel.\n */\n dispose() {\n if (this.isDisposed) {\n return;\n }\n this._isDisposed = true;\n this._disposed.emit(void 0);\n }\n /**\n * Handle an incoming message from the client.\n *\n * @param msg The message to handle\n */\n async handleMessage(msg) {\n this._busy(msg);\n this._parent = msg;\n const msgType = msg.header.msg_type;\n switch (msgType) {\n case 'kernel_info_request':\n await this._kernelInfo(msg);\n break;\n case 'execute_request':\n await this._execute(msg);\n break;\n case 'input_reply':\n this.inputReply(msg.content);\n break;\n case 'inspect_request':\n await this._inspect(msg);\n break;\n case 'is_complete_request':\n await this._isCompleteRequest(msg);\n break;\n case 'complete_request':\n await this._complete(msg);\n break;\n case 'history_request':\n await this._historyRequest(msg);\n break;\n case 'comm_open':\n await this.commOpen(msg);\n break;\n case 'comm_msg':\n await this.commMsg(msg);\n break;\n case 'comm_close':\n await this.commClose(msg);\n break;\n default:\n break;\n }\n this._idle(msg);\n }\n /**\n * Stream an event from the kernel\n *\n * @param parentHeader The parent header.\n * @param content The stream content.\n */\n stream(content, parentHeader = undefined) {\n var _a;\n const parentHeaderValue = typeof parentHeader !== 'undefined' ? parentHeader : this._parentHeader;\n const message = KernelMessage.createMessage({\n channel: 'iopub',\n msgType: 'stream',\n // TODO: better handle this\n session: (_a = parentHeaderValue === null || parentHeaderValue === void 0 ? void 0 : parentHeaderValue.session) !== null && _a !== void 0 ? _a : '',\n parentHeader: parentHeaderValue,\n content,\n });\n this._sendMessage(message);\n }\n /**\n * Send a `display_data` message to the client.\n *\n * @param parentHeader The parent header.\n * @param content The display_data content.\n */\n displayData(content, parentHeader = undefined) {\n var _a, _b;\n // Make sure metadata is always set\n const parentHeaderValue = typeof parentHeader !== 'undefined' ? parentHeader : this._parentHeader;\n content.metadata = (_a = content.metadata) !== null && _a !== void 0 ? _a : {};\n const message = KernelMessage.createMessage({\n channel: 'iopub',\n msgType: 'display_data',\n // TODO: better handle this\n session: (_b = parentHeaderValue === null || parentHeaderValue === void 0 ? void 0 : parentHeaderValue.session) !== null && _b !== void 0 ? _b : '',\n parentHeader: parentHeaderValue,\n content,\n });\n this._sendMessage(message);\n }\n /**\n * Send a `input_request` message to the client.\n *\n * @param parentHeader The parent header.\n * @param content The input_request content.\n */\n inputRequest(content, parentHeader = undefined) {\n var _a;\n const parentHeaderValue = typeof parentHeader !== 'undefined' ? parentHeader : this._parentHeader;\n const message = KernelMessage.createMessage({\n channel: 'stdin',\n msgType: 'input_request',\n // TODO: better handle this\n session: (_a = parentHeaderValue === null || parentHeaderValue === void 0 ? void 0 : parentHeaderValue.session) !== null && _a !== void 0 ? _a : '',\n parentHeader: parentHeaderValue,\n content,\n });\n this._sendMessage(message);\n }\n /**\n * Send an `execute_result` message.\n *\n * @param parentHeader The parent header.\n * @param content The execute result content.\n */\n publishExecuteResult(content, parentHeader = undefined) {\n var _a;\n const parentHeaderValue = typeof parentHeader !== 'undefined' ? parentHeader : this._parentHeader;\n const message = KernelMessage.createMessage({\n channel: 'iopub',\n msgType: 'execute_result',\n // TODO: better handle this\n session: (_a = parentHeaderValue === null || parentHeaderValue === void 0 ? void 0 : parentHeaderValue.session) !== null && _a !== void 0 ? _a : '',\n parentHeader: parentHeaderValue,\n content,\n });\n this._sendMessage(message);\n }\n /**\n * Send an `error` message to the client.\n *\n * @param parentHeader The parent header.\n * @param content The error content.\n */\n publishExecuteError(content, parentHeader = undefined) {\n var _a;\n const parentHeaderValue = typeof parentHeader !== 'undefined' ? parentHeader : this._parentHeader;\n const message = KernelMessage.createMessage({\n channel: 'iopub',\n msgType: 'error',\n // TODO: better handle this\n session: (_a = parentHeaderValue === null || parentHeaderValue === void 0 ? void 0 : parentHeaderValue.session) !== null && _a !== void 0 ? _a : '',\n parentHeader: parentHeaderValue,\n content,\n });\n this._sendMessage(message);\n }\n /**\n * Send a `update_display_data` message to the client.\n *\n * @param parentHeader The parent header.\n * @param content The update_display_data content.\n */\n updateDisplayData(content, parentHeader = undefined) {\n var _a;\n const parentHeaderValue = typeof parentHeader !== 'undefined' ? parentHeader : this._parentHeader;\n const message = KernelMessage.createMessage({\n channel: 'iopub',\n msgType: 'update_display_data',\n // TODO: better handle this\n session: (_a = parentHeaderValue === null || parentHeaderValue === void 0 ? void 0 : parentHeaderValue.session) !== null && _a !== void 0 ? _a : '',\n parentHeader: parentHeaderValue,\n content,\n });\n this._sendMessage(message);\n }\n /**\n * Send a `clear_output` message to the client.\n *\n * @param parentHeader The parent header.\n * @param content The clear_output content.\n */\n clearOutput(content, parentHeader = undefined) {\n var _a;\n const parentHeaderValue = typeof parentHeader !== 'undefined' ? parentHeader : this._parentHeader;\n const message = KernelMessage.createMessage({\n channel: 'iopub',\n msgType: 'clear_output',\n // TODO: better handle this\n session: (_a = parentHeaderValue === null || parentHeaderValue === void 0 ? void 0 : parentHeaderValue.session) !== null && _a !== void 0 ? _a : '',\n parentHeader: parentHeaderValue,\n content,\n });\n this._sendMessage(message);\n }\n /**\n * Send a `comm` message to the client.\n *\n * @param .\n */\n handleComm(type, content, metadata, buffers, parentHeader = undefined) {\n var _a;\n const parentHeaderValue = typeof parentHeader !== 'undefined' ? parentHeader : this._parentHeader;\n const message = KernelMessage.createMessage({\n channel: 'iopub',\n msgType: type,\n // TODO: better handle this\n session: (_a = parentHeaderValue === null || parentHeaderValue === void 0 ? void 0 : parentHeaderValue.session) !== null && _a !== void 0 ? _a : '',\n parentHeader: parentHeaderValue,\n content,\n metadata,\n buffers,\n });\n this._sendMessage(message);\n }\n /**\n * Send an 'idle' status message.\n *\n * @param parent The parent message\n */\n _idle(parent) {\n const message = KernelMessage.createMessage({\n msgType: 'status',\n session: parent.header.session,\n parentHeader: parent.header,\n channel: 'iopub',\n content: {\n execution_state: 'idle',\n },\n });\n this._sendMessage(message);\n }\n /**\n * Send a 'busy' status message.\n *\n * @param parent The parent message.\n */\n _busy(parent) {\n const message = KernelMessage.createMessage({\n msgType: 'status',\n session: parent.header.session,\n parentHeader: parent.header,\n channel: 'iopub',\n content: {\n execution_state: 'busy',\n },\n });\n this._sendMessage(message);\n }\n /**\n * Handle a kernel_info_request message\n *\n * @param parent The parent message.\n */\n async _kernelInfo(parent) {\n const content = await this.kernelInfoRequest();\n const message = KernelMessage.createMessage({\n msgType: 'kernel_info_reply',\n channel: 'shell',\n session: parent.header.session,\n parentHeader: parent.header,\n content,\n });\n this._sendMessage(message);\n }\n /**\n * Handle a `history_request` message\n *\n * @param msg The parent message.\n */\n async _historyRequest(msg) {\n const historyMsg = msg;\n const message = KernelMessage.createMessage({\n msgType: 'history_reply',\n channel: 'shell',\n parentHeader: historyMsg.header,\n session: msg.header.session,\n content: {\n status: 'ok',\n history: this._history,\n },\n });\n this._sendMessage(message);\n }\n /**\n * Send an `execute_input` message.\n *\n * @param msg The parent message.\n */\n _executeInput(msg) {\n const parent = msg;\n const code = parent.content.code;\n const message = KernelMessage.createMessage({\n msgType: 'execute_input',\n parentHeader: parent.header,\n channel: 'iopub',\n session: msg.header.session,\n content: {\n code,\n execution_count: this._executionCount,\n },\n });\n this._sendMessage(message);\n }\n /**\n * Handle an execute_request message.\n *\n * @param msg The parent message.\n */\n async _execute(msg) {\n const executeMsg = msg;\n const content = executeMsg.content;\n if (content.store_history) {\n this._executionCount++;\n }\n // TODO: handle differently\n this._parentHeader = executeMsg.header;\n this._executeInput(executeMsg);\n if (content.store_history) {\n this._history.push([0, 0, content.code]);\n }\n const reply = await this.executeRequest(executeMsg.content);\n const message = KernelMessage.createMessage({\n msgType: 'execute_reply',\n channel: 'shell',\n parentHeader: executeMsg.header,\n session: msg.header.session,\n content: reply,\n });\n this._sendMessage(message);\n }\n /**\n * Handle an complete_request message\n *\n * @param msg The parent message.\n */\n async _complete(msg) {\n const completeMsg = msg;\n const content = await this.completeRequest(completeMsg.content);\n const message = KernelMessage.createMessage({\n msgType: 'complete_reply',\n parentHeader: completeMsg.header,\n channel: 'shell',\n session: msg.header.session,\n content,\n });\n this._sendMessage(message);\n }\n /**\n * Handle an inspect_request message\n *\n * @param msg The parent message.\n */\n async _inspect(msg) {\n const inspectMsg = msg;\n const content = await this.inspectRequest(inspectMsg.content);\n const message = KernelMessage.createMessage({\n msgType: 'inspect_reply',\n parentHeader: inspectMsg.header,\n channel: 'shell',\n session: msg.header.session,\n content,\n });\n this._sendMessage(message);\n }\n /**\n * Handle an is_complete_request message\n *\n * @param msg The parent message.\n */\n async _isCompleteRequest(msg) {\n const isCompleteMsg = msg;\n const content = await this.isCompleteRequest(isCompleteMsg.content);\n const message = KernelMessage.createMessage({\n msgType: 'is_complete_reply',\n parentHeader: isCompleteMsg.header,\n channel: 'shell',\n session: msg.header.session,\n content,\n });\n this._sendMessage(message);\n }\n}\n//# sourceMappingURL=kernel.js.map","/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\nconst proxyMarker = Symbol(\"Comlink.proxy\");\nconst createEndpoint = Symbol(\"Comlink.endpoint\");\nconst releaseProxy = Symbol(\"Comlink.releaseProxy\");\nconst finalizer = Symbol(\"Comlink.finalizer\");\nconst throwMarker = Symbol(\"Comlink.thrown\");\nconst isObject = (val) => (typeof val === \"object\" && val !== null) || typeof val === \"function\";\n/**\n * Internal transfer handle to handle objects marked to proxy.\n */\nconst proxyTransferHandler = {\n canHandle: (val) => isObject(val) && val[proxyMarker],\n serialize(obj) {\n const { port1, port2 } = new MessageChannel();\n expose(obj, port1);\n return [port2, [port2]];\n },\n deserialize(port) {\n port.start();\n return wrap(port);\n },\n};\n/**\n * Internal transfer handler to handle thrown exceptions.\n */\nconst throwTransferHandler = {\n canHandle: (value) => isObject(value) && throwMarker in value,\n serialize({ value }) {\n let serialized;\n if (value instanceof Error) {\n serialized = {\n isError: true,\n value: {\n message: value.message,\n name: value.name,\n stack: value.stack,\n },\n };\n }\n else {\n serialized = { isError: false, value };\n }\n return [serialized, []];\n },\n deserialize(serialized) {\n if (serialized.isError) {\n throw Object.assign(new Error(serialized.value.message), serialized.value);\n }\n throw serialized.value;\n },\n};\n/**\n * Allows customizing the serialization of certain values.\n */\nconst transferHandlers = new Map([\n [\"proxy\", proxyTransferHandler],\n [\"throw\", throwTransferHandler],\n]);\nfunction isAllowedOrigin(allowedOrigins, origin) {\n for (const allowedOrigin of allowedOrigins) {\n if (origin === allowedOrigin || allowedOrigin === \"*\") {\n return true;\n }\n if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) {\n return true;\n }\n }\n return false;\n}\nfunction expose(obj, ep = globalThis, allowedOrigins = [\"*\"]) {\n ep.addEventListener(\"message\", function callback(ev) {\n if (!ev || !ev.data) {\n return;\n }\n if (!isAllowedOrigin(allowedOrigins, ev.origin)) {\n console.warn(`Invalid origin '${ev.origin}' for comlink proxy`);\n return;\n }\n const { id, type, path } = Object.assign({ path: [] }, ev.data);\n const argumentList = (ev.data.argumentList || []).map(fromWireValue);\n let returnValue;\n try {\n const parent = path.slice(0, -1).reduce((obj, prop) => obj[prop], obj);\n const rawValue = path.reduce((obj, prop) => obj[prop], obj);\n switch (type) {\n case \"GET\" /* MessageType.GET */:\n {\n returnValue = rawValue;\n }\n break;\n case \"SET\" /* MessageType.SET */:\n {\n parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);\n returnValue = true;\n }\n break;\n case \"APPLY\" /* MessageType.APPLY */:\n {\n returnValue = rawValue.apply(parent, argumentList);\n }\n break;\n case \"CONSTRUCT\" /* MessageType.CONSTRUCT */:\n {\n const value = new rawValue(...argumentList);\n returnValue = proxy(value);\n }\n break;\n case \"ENDPOINT\" /* MessageType.ENDPOINT */:\n {\n const { port1, port2 } = new MessageChannel();\n expose(obj, port2);\n returnValue = transfer(port1, [port1]);\n }\n break;\n case \"RELEASE\" /* MessageType.RELEASE */:\n {\n returnValue = undefined;\n }\n break;\n default:\n return;\n }\n }\n catch (value) {\n returnValue = { value, [throwMarker]: 0 };\n }\n Promise.resolve(returnValue)\n .catch((value) => {\n return { value, [throwMarker]: 0 };\n })\n .then((returnValue) => {\n const [wireValue, transferables] = toWireValue(returnValue);\n ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);\n if (type === \"RELEASE\" /* MessageType.RELEASE */) {\n // detach and deactive after sending release response above.\n ep.removeEventListener(\"message\", callback);\n closeEndPoint(ep);\n if (finalizer in obj && typeof obj[finalizer] === \"function\") {\n obj[finalizer]();\n }\n }\n })\n .catch((error) => {\n // Send Serialization Error To Caller\n const [wireValue, transferables] = toWireValue({\n value: new TypeError(\"Unserializable return value\"),\n [throwMarker]: 0,\n });\n ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);\n });\n });\n if (ep.start) {\n ep.start();\n }\n}\nfunction isMessagePort(endpoint) {\n return endpoint.constructor.name === \"MessagePort\";\n}\nfunction closeEndPoint(endpoint) {\n if (isMessagePort(endpoint))\n endpoint.close();\n}\nfunction wrap(ep, target) {\n return createProxy(ep, [], target);\n}\nfunction throwIfProxyReleased(isReleased) {\n if (isReleased) {\n throw new Error(\"Proxy has been released and is not useable\");\n }\n}\nfunction releaseEndpoint(ep) {\n return requestResponseMessage(ep, {\n type: \"RELEASE\" /* MessageType.RELEASE */,\n }).then(() => {\n closeEndPoint(ep);\n });\n}\nconst proxyCounter = new WeakMap();\nconst proxyFinalizers = \"FinalizationRegistry\" in globalThis &&\n new FinalizationRegistry((ep) => {\n const newCount = (proxyCounter.get(ep) || 0) - 1;\n proxyCounter.set(ep, newCount);\n if (newCount === 0) {\n releaseEndpoint(ep);\n }\n });\nfunction registerProxy(proxy, ep) {\n const newCount = (proxyCounter.get(ep) || 0) + 1;\n proxyCounter.set(ep, newCount);\n if (proxyFinalizers) {\n proxyFinalizers.register(proxy, ep, proxy);\n }\n}\nfunction unregisterProxy(proxy) {\n if (proxyFinalizers) {\n proxyFinalizers.unregister(proxy);\n }\n}\nfunction createProxy(ep, path = [], target = function () { }) {\n let isProxyReleased = false;\n const proxy = new Proxy(target, {\n get(_target, prop) {\n throwIfProxyReleased(isProxyReleased);\n if (prop === releaseProxy) {\n return () => {\n unregisterProxy(proxy);\n releaseEndpoint(ep);\n isProxyReleased = true;\n };\n }\n if (prop === \"then\") {\n if (path.length === 0) {\n return { then: () => proxy };\n }\n const r = requestResponseMessage(ep, {\n type: \"GET\" /* MessageType.GET */,\n path: path.map((p) => p.toString()),\n }).then(fromWireValue);\n return r.then.bind(r);\n }\n return createProxy(ep, [...path, prop]);\n },\n set(_target, prop, rawValue) {\n throwIfProxyReleased(isProxyReleased);\n // FIXME: ES6 Proxy Handler `set` methods are supposed to return a\n // boolean. To show good will, we return true asynchronously ¯\\_(ツ)_/¯\n const [value, transferables] = toWireValue(rawValue);\n return requestResponseMessage(ep, {\n type: \"SET\" /* MessageType.SET */,\n path: [...path, prop].map((p) => p.toString()),\n value,\n }, transferables).then(fromWireValue);\n },\n apply(_target, _thisArg, rawArgumentList) {\n throwIfProxyReleased(isProxyReleased);\n const last = path[path.length - 1];\n if (last === createEndpoint) {\n return requestResponseMessage(ep, {\n type: \"ENDPOINT\" /* MessageType.ENDPOINT */,\n }).then(fromWireValue);\n }\n // We just pretend that `bind()` didn’t happen.\n if (last === \"bind\") {\n return createProxy(ep, path.slice(0, -1));\n }\n const [argumentList, transferables] = processArguments(rawArgumentList);\n return requestResponseMessage(ep, {\n type: \"APPLY\" /* MessageType.APPLY */,\n path: path.map((p) => p.toString()),\n argumentList,\n }, transferables).then(fromWireValue);\n },\n construct(_target, rawArgumentList) {\n throwIfProxyReleased(isProxyReleased);\n const [argumentList, transferables] = processArguments(rawArgumentList);\n return requestResponseMessage(ep, {\n type: \"CONSTRUCT\" /* MessageType.CONSTRUCT */,\n path: path.map((p) => p.toString()),\n argumentList,\n }, transferables).then(fromWireValue);\n },\n });\n registerProxy(proxy, ep);\n return proxy;\n}\nfunction myFlat(arr) {\n return Array.prototype.concat.apply([], arr);\n}\nfunction processArguments(argumentList) {\n const processed = argumentList.map(toWireValue);\n return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))];\n}\nconst transferCache = new WeakMap();\nfunction transfer(obj, transfers) {\n transferCache.set(obj, transfers);\n return obj;\n}\nfunction proxy(obj) {\n return Object.assign(obj, { [proxyMarker]: true });\n}\nfunction windowEndpoint(w, context = globalThis, targetOrigin = \"*\") {\n return {\n postMessage: (msg, transferables) => w.postMessage(msg, targetOrigin, transferables),\n addEventListener: context.addEventListener.bind(context),\n removeEventListener: context.removeEventListener.bind(context),\n };\n}\nfunction toWireValue(value) {\n for (const [name, handler] of transferHandlers) {\n if (handler.canHandle(value)) {\n const [serializedValue, transferables] = handler.serialize(value);\n return [\n {\n type: \"HANDLER\" /* WireValueType.HANDLER */,\n name,\n value: serializedValue,\n },\n transferables,\n ];\n }\n }\n return [\n {\n type: \"RAW\" /* WireValueType.RAW */,\n value,\n },\n transferCache.get(value) || [],\n ];\n}\nfunction fromWireValue(value) {\n switch (value.type) {\n case \"HANDLER\" /* WireValueType.HANDLER */:\n return transferHandlers.get(value.name).deserialize(value.value);\n case \"RAW\" /* WireValueType.RAW */:\n return value.value;\n }\n}\nfunction requestResponseMessage(ep, msg, transfers) {\n return new Promise((resolve) => {\n const id = generateUUID();\n ep.addEventListener(\"message\", function l(ev) {\n if (!ev.data || !ev.data.id || ev.data.id !== id) {\n return;\n }\n ep.removeEventListener(\"message\", l);\n resolve(ev.data);\n });\n if (ep.start) {\n ep.start();\n }\n ep.postMessage(Object.assign({ id }, msg), transfers);\n });\n}\nfunction generateUUID() {\n return new Array(4)\n .fill(0)\n .map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16))\n .join(\"-\");\n}\n\nexport { createEndpoint, expose, finalizer, proxy, proxyMarker, releaseProxy, transfer, transferHandlers, windowEndpoint, wrap };\n//# sourceMappingURL=comlink.mjs.map\n","import { PromiseDelegate } from '@lumino/coreutils';\nimport { PageConfig } from '@jupyterlab/coreutils';\nimport { BaseKernel } from '@jupyterlite/kernel';\nimport { wrap } from 'comlink';\nimport { allJSONUrl, pipliteWheelUrl } from './_pypi';\n/**\n * A kernel that executes Python code with Pyodide.\n */\nexport class PyodideKernel extends BaseKernel {\n /**\n * Instantiate a new PyodideKernel\n *\n * @param options The instantiation options for a new PyodideKernel\n */\n constructor(options) {\n super(options);\n this._ready = new PromiseDelegate();\n this._worker = this.initWorker(options);\n this._worker.onmessage = (e) => this._processWorkerMessage(e.data);\n this._remoteKernel = wrap(this._worker);\n this.initRemote(options);\n }\n /**\n * Load the worker.\n *\n * ### Note\n *\n * Subclasses must implement this typographically almost _exactly_ for\n * webpack to find it.\n */\n initWorker(options) {\n return new Worker(new URL('./comlink.worker.js', import.meta.url), {\n type: 'module',\n });\n }\n async initRemote(options) {\n const remoteOptions = this.initRemoteOptions(options);\n await this._remoteKernel.initialize(remoteOptions);\n this._ready.resolve();\n }\n initRemoteOptions(options) {\n const { pyodideUrl } = options;\n const indexUrl = pyodideUrl.slice(0, pyodideUrl.lastIndexOf('/') + 1);\n const baseUrl = PageConfig.getBaseUrl();\n const pipliteUrls = [...(options.pipliteUrls || []), allJSONUrl.default];\n const disablePyPIFallback = !!options.disablePyPIFallback;\n return {\n baseUrl,\n pyodideUrl,\n indexUrl,\n pipliteWheelUrl: options.pipliteWheelUrl || pipliteWheelUrl.default,\n pipliteUrls,\n disablePyPIFallback,\n location: this.location,\n mountDrive: options.mountDrive,\n };\n }\n /**\n * Dispose the kernel.\n */\n dispose() {\n if (this.isDisposed) {\n return;\n }\n this._worker.terminate();\n this._worker = null;\n super.dispose();\n }\n /**\n * A promise that is fulfilled when the kernel is ready.\n */\n get ready() {\n return this._ready.promise;\n }\n /**\n * Process a message coming from the pyodide web worker.\n *\n * @param msg The worker message to process.\n */\n _processWorkerMessage(msg) {\n var _a, _b, _c, _d, _e, _f, _g;\n if (!msg.type) {\n return;\n }\n switch (msg.type) {\n case 'stream': {\n const bundle = (_a = msg.bundle) !== null && _a !== void 0 ? _a : { name: 'stdout', text: '' };\n this.stream(bundle, msg.parentHeader);\n break;\n }\n case 'input_request': {\n const bundle = (_b = msg.content) !== null && _b !== void 0 ? _b : { prompt: '', password: false };\n this.inputRequest(bundle, msg.parentHeader);\n break;\n }\n case 'display_data': {\n const bundle = (_c = msg.bundle) !== null && _c !== void 0 ? _c : { data: {}, metadata: {}, transient: {} };\n this.displayData(bundle, msg.parentHeader);\n break;\n }\n case 'update_display_data': {\n const bundle = (_d = msg.bundle) !== null && _d !== void 0 ? _d : { data: {}, metadata: {}, transient: {} };\n this.updateDisplayData(bundle, msg.parentHeader);\n break;\n }\n case 'clear_output': {\n const bundle = (_e = msg.bundle) !== null && _e !== void 0 ? _e : { wait: false };\n this.clearOutput(bundle, msg.parentHeader);\n break;\n }\n case 'execute_result': {\n const bundle = (_f = msg.bundle) !== null && _f !== void 0 ? _f : {\n execution_count: 0,\n data: {},\n metadata: {},\n };\n this.publishExecuteResult(bundle, msg.parentHeader);\n break;\n }\n case 'execute_error': {\n const bundle = (_g = msg.bundle) !== null && _g !== void 0 ? _g : { ename: '', evalue: '', traceback: [] };\n this.publishExecuteError(bundle, msg.parentHeader);\n break;\n }\n case 'comm_msg':\n case 'comm_open':\n case 'comm_close': {\n this.handleComm(msg.type, msg.content, msg.metadata, msg.buffers, msg.parentHeader);\n break;\n }\n }\n }\n /**\n * Handle a kernel_info_request message\n */\n async kernelInfoRequest() {\n const content = {\n implementation: 'pyodide',\n implementation_version: '0.1.0',\n language_info: {\n codemirror_mode: {\n name: 'python',\n version: 3,\n },\n file_extension: '.py',\n mimetype: 'text/x-python',\n name: 'python',\n nbconvert_exporter: 'python',\n pygments_lexer: 'ipython3',\n version: '3.8',\n },\n protocol_version: '5.3',\n status: 'ok',\n banner: 'A WebAssembly-powered Python kernel backed by Pyodide',\n help_links: [\n {\n text: 'Python (WASM) Kernel',\n url: 'https://pyodide.org',\n },\n ],\n };\n return content;\n }\n /**\n * Handle an `execute_request` message\n *\n * @param msg The parent message.\n */\n async executeRequest(content) {\n await this.ready;\n const result = await this._remoteKernel.execute(content, this.parent);\n result.execution_count = this.executionCount;\n return result;\n }\n /**\n * Handle an complete_request message\n *\n * @param msg The parent message.\n */\n async completeRequest(content) {\n return await this._remoteKernel.complete(content, this.parent);\n }\n /**\n * Handle an `inspect_request` message.\n *\n * @param content - The content of the request.\n *\n * @returns A promise that resolves with the response message.\n */\n async inspectRequest(content) {\n return await this._remoteKernel.inspect(content, this.parent);\n }\n /**\n * Handle an `is_complete_request` message.\n *\n * @param content - The content of the request.\n *\n * @returns A promise that resolves with the response message.\n */\n async isCompleteRequest(content) {\n return await this._remoteKernel.isComplete(content, this.parent);\n }\n /**\n * Handle a `comm_info_request` message.\n *\n * @param content - The content of the request.\n *\n * @returns A promise that resolves with the response message.\n */\n async commInfoRequest(content) {\n return await this._remoteKernel.commInfo(content, this.parent);\n }\n /**\n * Send an `comm_open` message.\n *\n * @param msg - The comm_open message.\n */\n async commOpen(msg) {\n return await this._remoteKernel.commOpen(msg, this.parent);\n }\n /**\n * Send an `comm_msg` message.\n *\n * @param msg - The comm_msg message.\n */\n async commMsg(msg) {\n return await this._remoteKernel.commMsg(msg, this.parent);\n }\n /**\n * Send an `comm_close` message.\n *\n * @param close - The comm_close message.\n */\n async commClose(msg) {\n return await this._remoteKernel.commClose(msg, this.parent);\n }\n /**\n * Send an `input_reply` message.\n *\n * @param content - The content of the reply.\n */\n async inputReply(content) {\n return await this._remoteKernel.inputReply(content, this.parent);\n }\n}\n","function webpackEmptyAsyncContext(req) {\n\t// Here Promise.resolve().then() is used instead of new Promise() to prevent\n\t// uncaught exception popping up in devtools\n\treturn Promise.resolve().then(() => {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t});\n}\nwebpackEmptyAsyncContext.keys = () => ([]);\nwebpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;\nwebpackEmptyAsyncContext.id = 265;\nmodule.exports = webpackEmptyAsyncContext;"],"names":["BaseKernel","constructor","options","this","_history","_executionCount","_isDisposed","_disposed","Signal","_parentHeader","undefined","_parent","id","name","location","sendMessage","_id","_name","_location","_sendMessage","ready","Promise","resolve","isDisposed","disposed","executionCount","parentHeader","parent","dispose","emit","async","msg","_busy","header","msg_type","_kernelInfo","_execute","inputReply","content","_inspect","_isCompleteRequest","_complete","_historyRequest","commOpen","commMsg","commClose","_idle","stream","_a","parentHeaderValue","message","KernelMessage","channel","msgType","session","displayData","_b","metadata","inputRequest","publishExecuteResult","publishExecuteError","updateDisplayData","clearOutput","handleComm","type","buffers","execution_state","kernelInfoRequest","historyMsg","status","history","_executeInput","code","execution_count","executeMsg","store_history","push","reply","executeRequest","completeMsg","completeRequest","inspectMsg","inspectRequest","isCompleteMsg","isCompleteRequest","proxyMarker","Symbol","createEndpoint","releaseProxy","finalizer","throwMarker","isObject","val","transferHandlers","Map","canHandle","serialize","obj","port1","port2","MessageChannel","expose","deserialize","port","start","wrap","value","serialized","Error","isError","stack","Object","assign","ep","globalThis","allowedOrigins","addEventListener","callback","ev","data","origin","allowedOrigin","RegExp","test","isAllowedOrigin","console","warn","path","argumentList","map","fromWireValue","returnValue","slice","reduce","prop","rawValue","apply","proxy","transfers","transferCache","set","transfer","catch","then","wireValue","transferables","toWireValue","postMessage","removeEventListener","closeEndPoint","error","TypeError","endpoint","isMessagePort","close","target","createProxy","throwIfProxyReleased","isReleased","releaseEndpoint","requestResponseMessage","proxyCounter","WeakMap","proxyFinalizers","FinalizationRegistry","newCount","get","isProxyReleased","Proxy","_target","unregister","unregisterProxy","length","r","p","toString","bind","_thisArg","rawArgumentList","last","processArguments","construct","register","registerProxy","processed","v","arr","Array","prototype","concat","handler","serializedValue","fill","Math","floor","random","Number","MAX_SAFE_INTEGER","join","l","PyodideKernel","super","_ready","PromiseDelegate","_worker","initWorker","onmessage","e","_processWorkerMessage","_remoteKernel","initRemote","Worker","URL","remoteOptions","initRemoteOptions","initialize","pyodideUrl","indexUrl","lastIndexOf","baseUrl","PageConfig","pipliteUrls","disablePyPIFallback","pipliteWheelUrl","mountDrive","terminate","promise","_c","_d","_e","_f","_g","bundle","text","prompt","password","transient","wait","ename","evalue","traceback","implementation","implementation_version","language_info","codemirror_mode","version","file_extension","mimetype","nbconvert_exporter","pygments_lexer","protocol_version","banner","help_links","url","result","execute","complete","inspect","isComplete","commInfo","webpackEmptyAsyncContext","req","keys","module","exports"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/5144.index.js b/book/_build/html/_static/5144.index.js
new file mode 100644
index 0000000..67babe6
--- /dev/null
+++ b/book/_build/html/_static/5144.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[5144],{15144:(e,i,$)=>{function r(e){for(var i={},$=e.split(" "),r=0;r<$.length;++r)i[$[r]]=!0;return i}$.r(i),$.d(i,{mirc:()=>m});var t=r("$! $$ $& $? $+ $abook $abs $active $activecid $activewid $address $addtok $agent $agentname $agentstat $agentver $alias $and $anick $ansi2mirc $aop $appactive $appstate $asc $asctime $asin $atan $avoice $away $awaymsg $awaytime $banmask $base $bfind $binoff $biton $bnick $bvar $bytes $calc $cb $cd $ceil $chan $chanmodes $chantypes $chat $chr $cid $clevel $click $cmdbox $cmdline $cnick $color $com $comcall $comchan $comerr $compact $compress $comval $cos $count $cr $crc $creq $crlf $ctime $ctimer $ctrlenter $date $day $daylight $dbuh $dbuw $dccignore $dccport $dde $ddename $debug $decode $decompress $deltok $devent $dialog $did $didreg $didtok $didwm $disk $dlevel $dll $dllcall $dname $dns $duration $ebeeps $editbox $emailaddr $encode $error $eval $event $exist $feof $ferr $fgetc $file $filename $filtered $finddir $finddirn $findfile $findfilen $findtok $fline $floor $fopen $fread $fserve $fulladdress $fulldate $fullname $fullscreen $get $getdir $getdot $gettok $gmt $group $halted $hash $height $hfind $hget $highlight $hnick $hotline $hotlinepos $ial $ialchan $ibl $idle $iel $ifmatch $ignore $iif $iil $inelipse $ini $inmidi $inpaste $inpoly $input $inrect $inroundrect $insong $instok $int $inwave $ip $isalias $isbit $isdde $isdir $isfile $isid $islower $istok $isupper $keychar $keyrpt $keyval $knick $lactive $lactivecid $lactivewid $left $len $level $lf $line $lines $link $lock $lock $locked $log $logstamp $logstampfmt $longfn $longip $lower $ltimer $maddress $mask $matchkey $matchtok $md5 $me $menu $menubar $menucontext $menutype $mid $middir $mircdir $mircexe $mircini $mklogfn $mnick $mode $modefirst $modelast $modespl $mouse $msfile $network $newnick $nick $nofile $nopath $noqt $not $notags $notify $null $numeric $numok $oline $onpoly $opnick $or $ord $os $passivedcc $pic $play $pnick $port $portable $portfree $pos $prefix $prop $protect $puttok $qt $query $rand $r $rawmsg $read $readomo $readn $regex $regml $regsub $regsubex $remove $remtok $replace $replacex $reptok $result $rgb $right $round $scid $scon $script $scriptdir $scriptline $sdir $send $server $serverip $sfile $sha1 $shortfn $show $signal $sin $site $sline $snick $snicks $snotify $sock $sockbr $sockerr $sockname $sorttok $sound $sqrt $ssl $sreq $sslready $status $strip $str $stripped $syle $submenu $switchbar $tan $target $ticks $time $timer $timestamp $timestampfmt $timezone $tip $titlebar $toolbar $treebar $trust $ulevel $ulist $upper $uptime $url $usermode $v1 $v2 $var $vcmd $vcmdstat $vcmdver $version $vnick $vol $wid $width $wildsite $wildtok $window $wrap $xor"),a=r("abook ajinvite alias aline ame amsg anick aop auser autojoin avoice away background ban bcopy beep bread break breplace bset btrunc bunset bwrite channel clear clearall cline clipboard close cnick color comclose comopen comreg continue copy creq ctcpreply ctcps dcc dccserver dde ddeserver debug dec describe dialog did didtok disable disconnect dlevel dline dll dns dqwindow drawcopy drawdot drawfill drawline drawpic drawrect drawreplace drawrot drawsave drawscroll drawtext ebeeps echo editbox emailaddr enable events exit fclose filter findtext finger firewall flash flist flood flush flushini font fopen fseek fsend fserve fullname fwrite ghide gload gmove gopts goto gplay gpoint gqreq groups gshow gsize gstop gtalk gunload hadd halt haltdef hdec hdel help hfree hinc hload hmake hop hsave ial ialclear ialmark identd if ignore iline inc invite iuser join kick linesep links list load loadbuf localinfo log mdi me menubar mkdir mnick mode msg nick noop notice notify omsg onotice part partall pdcc perform play playctrl pop protect pvoice qme qmsg query queryn quit raw reload remini remote remove rename renwin reseterror resetidle return rlevel rline rmdir run ruser save savebuf saveini say scid scon server set showmirc signam sline sockaccept sockclose socklist socklisten sockmark sockopen sockpause sockread sockrename sockudp sockwrite sound speak splay sreq strip switchbar timer timestamp titlebar tnick tokenize toolbar topic tray treebar ulist unload unset unsetall updatenl url uwho var vcadd vcmd vcrem vol while whois window winhelp write writeint if isalnum isalpha isaop isavoice isban ischan ishop isignore isin isincs isletter islower isnotify isnum ison isop isprotect isreg isupper isvoice iswm iswmcs elseif else goto menu nicklist status title icon size option text edit button check radio box scroll list combo link tab item"),n=r("if elseif else and not or eq ne in ni for foreach while switch"),o=/[+\-*&%=<>!?^\/\|]/;function s(e,i,$){return i.tokenize=$,$(e,i)}function l(e,i){var $=i.beforeParams;i.beforeParams=!1;var r=e.next();if(/[\[\]{}\(\),\.]/.test(r))return"("==r&&$?i.inParams=!0:")"==r&&(i.inParams=!1),null;if(/\d/.test(r))return e.eatWhile(/[\w\.]/),"number";if("\\"==r)return e.eat("\\"),e.eat(/./),"number";if("/"==r&&e.eat("*"))return s(e,i,c);if(";"==r&&e.match(/ *\( *\(/))return s(e,i,d);if(";"!=r||i.inParams){if('"'==r)return e.eat(/"/),"keyword";if("$"==r)return e.eatWhile(/[$_a-z0-9A-Z\.:]/),t&&t.propertyIsEnumerable(e.current().toLowerCase())?"keyword":(i.beforeParams=!0,"builtin");if("%"==r)return e.eatWhile(/[^,\s()]/),i.beforeParams=!0,"string";if(o.test(r))return e.eatWhile(o),"operator";e.eatWhile(/[\w\$_{}]/);var l=e.current().toLowerCase();return a&&a.propertyIsEnumerable(l)?"keyword":n&&n.propertyIsEnumerable(l)?(i.beforeParams=!0,"keyword"):null}return e.skipToEnd(),"comment"}function c(e,i){for(var $,r=!1;$=e.next();){if("/"==$&&r){i.tokenize=l;break}r="*"==$}return"comment"}function d(e,i){for(var $,r=0;$=e.next();){if(";"==$&&2==r){i.tokenize=l;break}")"==$?r++:" "!=$&&(r=0)}return"meta"}const m={name:"mirc",startState:function(){return{tokenize:l,beforeParams:!1,inParams:!1}},token:function(e,i){return e.eatSpace()?null:i.tokenize(e,i)}}}}]);
+//# sourceMappingURL=5144.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/5144.index.js.map b/book/_build/html/_static/5144.index.js.map
new file mode 100644
index 0000000..0a69a3a
--- /dev/null
+++ b/book/_build/html/_static/5144.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"5144.index.js","mappings":"+FAAA,SAASA,EAAWC,GAElB,IADA,IAAIC,EAAM,CAAC,EAAGC,EAAQF,EAAIG,MAAM,KACvBC,EAAI,EAAGA,EAAIF,EAAMG,SAAUD,EAAGH,EAAIC,EAAME,KAAM,EACvD,OAAOH,CACT,C,2BACA,IAAIK,EAAWP,EAAW,ohFAoCtBQ,EAAWR,EAAW,m0DAyBtBS,EAAYT,EAAW,kEACvBU,EAAiB,qBACrB,SAASC,EAAMC,EAAQC,EAAOC,GAE5B,OADAD,EAAME,SAAWD,EACVA,EAAEF,EAAQC,EACnB,CACA,SAASG,EAAUJ,EAAQC,GACzB,IAAII,EAAeJ,EAAMI,aACzBJ,EAAMI,cAAe,EACrB,IAAIC,EAAKN,EAAOO,OAChB,GAAI,kBAAkBC,KAAKF,GAGzB,MAFU,KAANA,GAAaD,EAAcJ,EAAMQ,UAAW,EACjC,KAANH,IAAWL,EAAMQ,UAAW,GAC9B,KAEJ,GAAI,KAAKD,KAAKF,GAEjB,OADAN,EAAOU,SAAS,UACT,SAEJ,GAAU,MAANJ,EAGP,OAFAN,EAAOW,IAAI,MACXX,EAAOW,IAAI,KACJ,SAEJ,GAAU,KAANL,GAAaN,EAAOW,IAAI,KAC/B,OAAOZ,EAAMC,EAAQC,EAAOW,GAEzB,GAAU,KAANN,GAAaN,EAAOa,MAAM,YACjC,OAAOd,EAAMC,EAAQC,EAAOa,GAEzB,GAAU,KAANR,GAAcL,EAAMQ,SAIxB,IAAU,KAANH,EAEP,OADAN,EAAOW,IAAI,KACJ,UAEJ,GAAU,KAANL,EAEP,OADAN,EAAOU,SAAS,oBACZf,GAAYA,EAASoB,qBAAqBf,EAAOgB,UAAUC,eACtD,WAGPhB,EAAMI,cAAe,EACd,WAGN,GAAU,KAANC,EAGP,OAFAN,EAAOU,SAAS,YAChBT,EAAMI,cAAe,EACd,SAEJ,GAAIP,EAAeU,KAAKF,GAE3B,OADAN,EAAOU,SAASZ,GACT,WAGPE,EAAOU,SAAS,aAChB,IAAIQ,EAAOlB,EAAOgB,UAAUC,cAC5B,OAAIrB,GAAYA,EAASmB,qBAAqBG,GACrC,UACLrB,GAAaA,EAAUkB,qBAAqBG,IAC9CjB,EAAMI,cAAe,EACd,WAEF,IACT,CAnCE,OADAL,EAAOmB,YACA,SAoCX,CACA,SAASP,EAAaZ,EAAQC,GAE5B,IADA,IAAsBK,EAAlBc,GAAW,EACRd,EAAKN,EAAOO,QAAQ,CACzB,GAAU,KAAND,GAAac,EAAU,CACzBnB,EAAME,SAAWC,EACjB,KACF,CACAgB,EAAkB,KAANd,CACd,CACA,MAAO,SACT,CACA,SAASQ,EAAcd,EAAQC,GAE7B,IADA,IAAkBK,EAAdc,EAAW,EACRd,EAAKN,EAAOO,QAAQ,CACzB,GAAU,KAAND,GAAyB,GAAZc,EAAe,CAC9BnB,EAAME,SAAWC,EACjB,KACF,CACU,KAANE,EACFc,IACa,KAANd,IACPc,EAAW,EACf,CACA,MAAO,MACT,CACO,MAAMC,EAAO,CAClBC,KAAM,OACNC,WAAY,WACV,MAAO,CACLpB,SAAUC,EACVC,cAAc,EACdI,UAAU,EAEd,EACAe,MAAO,SAASxB,EAAQC,GACtB,OAAID,EAAOyB,WAAmB,KACvBxB,EAAME,SAASH,EAAQC,EAChC,E","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/mirc.js"],"sourcesContent":["function parseWords(str) {\n var obj = {}, words = str.split(\" \");\n for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n return obj;\n}\nvar specials = parseWords(\"$! $$ $& $? $+ $abook $abs $active $activecid \" +\n \"$activewid $address $addtok $agent $agentname $agentstat $agentver \" +\n \"$alias $and $anick $ansi2mirc $aop $appactive $appstate $asc $asctime \" +\n \"$asin $atan $avoice $away $awaymsg $awaytime $banmask $base $bfind \" +\n \"$binoff $biton $bnick $bvar $bytes $calc $cb $cd $ceil $chan $chanmodes \" +\n \"$chantypes $chat $chr $cid $clevel $click $cmdbox $cmdline $cnick $color \" +\n \"$com $comcall $comchan $comerr $compact $compress $comval $cos $count \" +\n \"$cr $crc $creq $crlf $ctime $ctimer $ctrlenter $date $day $daylight \" +\n \"$dbuh $dbuw $dccignore $dccport $dde $ddename $debug $decode $decompress \" +\n \"$deltok $devent $dialog $did $didreg $didtok $didwm $disk $dlevel $dll \" +\n \"$dllcall $dname $dns $duration $ebeeps $editbox $emailaddr $encode $error \" +\n \"$eval $event $exist $feof $ferr $fgetc $file $filename $filtered $finddir \" +\n \"$finddirn $findfile $findfilen $findtok $fline $floor $fopen $fread $fserve \" +\n \"$fulladdress $fulldate $fullname $fullscreen $get $getdir $getdot $gettok $gmt \" +\n \"$group $halted $hash $height $hfind $hget $highlight $hnick $hotline \" +\n \"$hotlinepos $ial $ialchan $ibl $idle $iel $ifmatch $ignore $iif $iil \" +\n \"$inelipse $ini $inmidi $inpaste $inpoly $input $inrect $inroundrect \" +\n \"$insong $instok $int $inwave $ip $isalias $isbit $isdde $isdir $isfile \" +\n \"$isid $islower $istok $isupper $keychar $keyrpt $keyval $knick $lactive \" +\n \"$lactivecid $lactivewid $left $len $level $lf $line $lines $link $lock \" +\n \"$lock $locked $log $logstamp $logstampfmt $longfn $longip $lower $ltimer \" +\n \"$maddress $mask $matchkey $matchtok $md5 $me $menu $menubar $menucontext \" +\n \"$menutype $mid $middir $mircdir $mircexe $mircini $mklogfn $mnick $mode \" +\n \"$modefirst $modelast $modespl $mouse $msfile $network $newnick $nick $nofile \" +\n \"$nopath $noqt $not $notags $notify $null $numeric $numok $oline $onpoly \" +\n \"$opnick $or $ord $os $passivedcc $pic $play $pnick $port $portable $portfree \" +\n \"$pos $prefix $prop $protect $puttok $qt $query $rand $r $rawmsg $read $readomo \" +\n \"$readn $regex $regml $regsub $regsubex $remove $remtok $replace $replacex \" +\n \"$reptok $result $rgb $right $round $scid $scon $script $scriptdir $scriptline \" +\n \"$sdir $send $server $serverip $sfile $sha1 $shortfn $show $signal $sin \" +\n \"$site $sline $snick $snicks $snotify $sock $sockbr $sockerr $sockname \" +\n \"$sorttok $sound $sqrt $ssl $sreq $sslready $status $strip $str $stripped \" +\n \"$syle $submenu $switchbar $tan $target $ticks $time $timer $timestamp \" +\n \"$timestampfmt $timezone $tip $titlebar $toolbar $treebar $trust $ulevel \" +\n \"$ulist $upper $uptime $url $usermode $v1 $v2 $var $vcmd $vcmdstat $vcmdver \" +\n \"$version $vnick $vol $wid $width $wildsite $wildtok $window $wrap $xor\");\nvar keywords = parseWords(\"abook ajinvite alias aline ame amsg anick aop auser autojoin avoice \" +\n \"away background ban bcopy beep bread break breplace bset btrunc bunset bwrite \" +\n \"channel clear clearall cline clipboard close cnick color comclose comopen \" +\n \"comreg continue copy creq ctcpreply ctcps dcc dccserver dde ddeserver \" +\n \"debug dec describe dialog did didtok disable disconnect dlevel dline dll \" +\n \"dns dqwindow drawcopy drawdot drawfill drawline drawpic drawrect drawreplace \" +\n \"drawrot drawsave drawscroll drawtext ebeeps echo editbox emailaddr enable \" +\n \"events exit fclose filter findtext finger firewall flash flist flood flush \" +\n \"flushini font fopen fseek fsend fserve fullname fwrite ghide gload gmove \" +\n \"gopts goto gplay gpoint gqreq groups gshow gsize gstop gtalk gunload hadd \" +\n \"halt haltdef hdec hdel help hfree hinc hload hmake hop hsave ial ialclear \" +\n \"ialmark identd if ignore iline inc invite iuser join kick linesep links list \" +\n \"load loadbuf localinfo log mdi me menubar mkdir mnick mode msg nick noop notice \" +\n \"notify omsg onotice part partall pdcc perform play playctrl pop protect pvoice \" +\n \"qme qmsg query queryn quit raw reload remini remote remove rename renwin \" +\n \"reseterror resetidle return rlevel rline rmdir run ruser save savebuf saveini \" +\n \"say scid scon server set showmirc signam sline sockaccept sockclose socklist \" +\n \"socklisten sockmark sockopen sockpause sockread sockrename sockudp sockwrite \" +\n \"sound speak splay sreq strip switchbar timer timestamp titlebar tnick tokenize \" +\n \"toolbar topic tray treebar ulist unload unset unsetall updatenl url uwho \" +\n \"var vcadd vcmd vcrem vol while whois window winhelp write writeint if isalnum \" +\n \"isalpha isaop isavoice isban ischan ishop isignore isin isincs isletter islower \" +\n \"isnotify isnum ison isop isprotect isreg isupper isvoice iswm iswmcs \" +\n \"elseif else goto menu nicklist status title icon size option text edit \" +\n \"button check radio box scroll list combo link tab item\");\nvar functions = parseWords(\"if elseif else and not or eq ne in ni for foreach while switch\");\nvar isOperatorChar = /[+\\-*&%=<>!?^\\/\\|]/;\nfunction chain(stream, state, f) {\n state.tokenize = f;\n return f(stream, state);\n}\nfunction tokenBase(stream, state) {\n var beforeParams = state.beforeParams;\n state.beforeParams = false;\n var ch = stream.next();\n if (/[\\[\\]{}\\(\\),\\.]/.test(ch)) {\n if (ch == \"(\" && beforeParams) state.inParams = true;\n else if (ch == \")\") state.inParams = false;\n return null;\n }\n else if (/\\d/.test(ch)) {\n stream.eatWhile(/[\\w\\.]/);\n return \"number\";\n }\n else if (ch == \"\\\\\") {\n stream.eat(\"\\\\\");\n stream.eat(/./);\n return \"number\";\n }\n else if (ch == \"/\" && stream.eat(\"*\")) {\n return chain(stream, state, tokenComment);\n }\n else if (ch == \";\" && stream.match(/ *\\( *\\(/)) {\n return chain(stream, state, tokenUnparsed);\n }\n else if (ch == \";\" && !state.inParams) {\n stream.skipToEnd();\n return \"comment\";\n }\n else if (ch == '\"') {\n stream.eat(/\"/);\n return \"keyword\";\n }\n else if (ch == \"$\") {\n stream.eatWhile(/[$_a-z0-9A-Z\\.:]/);\n if (specials && specials.propertyIsEnumerable(stream.current().toLowerCase())) {\n return \"keyword\";\n }\n else {\n state.beforeParams = true;\n return \"builtin\";\n }\n }\n else if (ch == \"%\") {\n stream.eatWhile(/[^,\\s()]/);\n state.beforeParams = true;\n return \"string\";\n }\n else if (isOperatorChar.test(ch)) {\n stream.eatWhile(isOperatorChar);\n return \"operator\";\n }\n else {\n stream.eatWhile(/[\\w\\$_{}]/);\n var word = stream.current().toLowerCase();\n if (keywords && keywords.propertyIsEnumerable(word))\n return \"keyword\";\n if (functions && functions.propertyIsEnumerable(word)) {\n state.beforeParams = true;\n return \"keyword\";\n }\n return null;\n }\n}\nfunction tokenComment(stream, state) {\n var maybeEnd = false, ch;\n while (ch = stream.next()) {\n if (ch == \"/\" && maybeEnd) {\n state.tokenize = tokenBase;\n break;\n }\n maybeEnd = (ch == \"*\");\n }\n return \"comment\";\n}\nfunction tokenUnparsed(stream, state) {\n var maybeEnd = 0, ch;\n while (ch = stream.next()) {\n if (ch == \";\" && maybeEnd == 2) {\n state.tokenize = tokenBase;\n break;\n }\n if (ch == \")\")\n maybeEnd++;\n else if (ch != \" \")\n maybeEnd = 0;\n }\n return \"meta\";\n}\nexport const mirc = {\n name: \"mirc\",\n startState: function() {\n return {\n tokenize: tokenBase,\n beforeParams: false,\n inParams: false\n };\n },\n token: function(stream, state) {\n if (stream.eatSpace()) return null;\n return state.tokenize(stream, state);\n }\n};\n"],"names":["parseWords","str","obj","words","split","i","length","specials","keywords","functions","isOperatorChar","chain","stream","state","f","tokenize","tokenBase","beforeParams","ch","next","test","inParams","eatWhile","eat","tokenComment","match","tokenUnparsed","propertyIsEnumerable","current","toLowerCase","word","skipToEnd","maybeEnd","mirc","name","startState","token","eatSpace"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/5199.index.js b/book/_build/html/_static/5199.index.js
new file mode 100644
index 0000000..323f06d
--- /dev/null
+++ b/book/_build/html/_static/5199.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[5199],{85199:(e,t,r)=>{function n(e){for(var t={},r=0,n=e.length;rs});var a=n(["note","across","when","variant","until","unique","undefine","then","strip","select","retry","rescue","require","rename","reference","redefine","prefix","once","old","obsolete","loop","local","like","is","inspect","infix","include","if","frozen","from","external","export","ensure","end","elseif","else","do","creation","create","check","alias","agent","separate","invariant","inherit","indexing","feature","expanded","deferred","class","Void","True","Result","Precursor","False","Current","create","attached","detachable","as","and","implies","not","or"]),i=n([":=","and then","and","or","<<",">>"]);function o(e,t){if(e.eatSpace())return null;var r,n=e.next();return'"'==n||"'"==n?function(e,t,r){return r.tokenize.push(e),e(t,r)}((r=n,"string",function(e,t){for(var n,a=!1;null!=(n=e.next());){if(n==r&&!a){t.tokenize.pop();break}a=!a&&"%"==n}return"string"}),e,t):"-"==n&&e.eat("-")?(e.skipToEnd(),"comment"):":"==n&&e.eat("=")?"operator":/[0-9]/.test(n)?(e.eatWhile(/[xXbBCc0-9\.]/),e.eat(/[\?\!]/),"variable"):/[a-zA-Z_0-9]/.test(n)?(e.eatWhile(/[a-zA-Z_0-9]/),e.eat(/[\?\!]/),"variable"):/[=+\-\/*^%<>~]/.test(n)?(e.eatWhile(/[=+\-\/*^%<>~]/),"operator"):null}const s={name:"eiffel",startState:function(){return{tokenize:[o]}},token:function(e,t){var r=t.tokenize[t.tokenize.length-1](e,t);if("variable"==r){var n=e.current();r=a.propertyIsEnumerable(e.current())?"keyword":i.propertyIsEnumerable(e.current())?"operator":/^[A-Z][A-Z_0-9]*$/g.test(n)?"tag":/^0[bB][0-1]+$/g.test(n)||/^0[cC][0-7]+$/g.test(n)||/^0[xX][a-fA-F0-9]+$/g.test(n)||/^([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+)$/g.test(n)||/^[0-9]+$/g.test(n)?"number":"variable"}return r},languageData:{commentTokens:{line:"--"}}}}}]);
+//# sourceMappingURL=5199.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/5199.index.js.map b/book/_build/html/_static/5199.index.js.map
new file mode 100644
index 0000000..8647b74
--- /dev/null
+++ b/book/_build/html/_static/5199.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"5199.index.js","mappings":"+FAAA,SAASA,EAAQC,GAEf,IADA,IAAIC,EAAI,CAAC,EACAC,EAAI,EAAGC,EAAIH,EAAMI,OAAQF,EAAIC,IAAKD,EAAGD,EAAED,EAAME,KAAM,EAC5D,OAAOD,CACT,C,6BACA,IAAII,EAAWN,EAAQ,CACrB,OACA,SACA,OACA,UACA,QACA,SACA,WACA,OACA,QACA,SACA,QACA,SACA,UACA,SACA,YACA,WACA,SACA,OACA,MACA,WACA,OACA,QACA,OACA,KACA,UACA,QACA,UACA,KACA,SACA,OACA,WACA,SACA,SACA,MACA,SACA,OACA,KACA,WACA,SACA,QACA,QACA,QACA,WACA,YACA,UACA,WACA,UACA,WACA,WACA,QACA,OACA,OACA,SACA,YACA,QACA,UACA,SACA,WACA,aACA,KACA,MACA,UACA,MACA,OAEEO,EAAYP,EAAQ,CAAC,KAAM,WAAW,MAAO,KAAK,KAAK,OAO3D,SAASQ,EAAUC,EAAQC,GACzB,GAAID,EAAOE,WAAY,OAAO,KAC9B,IAwBkBC,EAxBdC,EAAKJ,EAAOK,OAChB,MAAU,KAAND,GAAiB,KAANA,EARjB,SAAeE,EAAQN,EAAQC,GAE7B,OADAA,EAAMM,SAASC,KAAKF,GACbA,EAAON,EAAQC,EACxB,CAMWQ,EAsBSN,EAtBQC,EAAI,SAuBvB,SAASJ,EAAQC,GAEtB,IADA,IAAqBG,EAAjBM,GAAU,EACiB,OAAvBN,EAAKJ,EAAOK,SAAiB,CACnC,GAAID,GAAMD,IAAwBO,EAAU,CAC1CT,EAAMM,SAASI,MACf,KACF,CACAD,GAAWA,GAAiB,KAANN,CACxB,CACA,MAhC4B,QAiC9B,GAjCyCJ,EAAQC,GAChC,KAANG,GAAWJ,EAAOY,IAAI,MAC/BZ,EAAOa,YACA,WACQ,KAANT,GAAWJ,EAAOY,IAAI,KACxB,WACE,QAAQE,KAAKV,IACtBJ,EAAOe,SAAS,iBAChBf,EAAOY,IAAI,UACJ,YACE,eAAeE,KAAKV,IAC7BJ,EAAOe,SAAS,gBAChBf,EAAOY,IAAI,UACJ,YACE,iBAAiBE,KAAKV,IAC/BJ,EAAOe,SAAS,kBACT,YAEA,IAEX,CAgBO,MAAMC,EAAS,CACpBC,KAAM,SACNC,WAAY,WACV,MAAO,CAACX,SAAU,CAACR,GACrB,EAEAoB,MAAO,SAASnB,EAAQC,GACtB,IAAImB,EAAQnB,EAAMM,SAASN,EAAMM,SAASX,OAAO,GAAGI,EAAQC,GAC5D,GAAa,YAATmB,EAAqB,CACvB,IAAIC,EAAOrB,EAAOsB,UAClBF,EAAQvB,EAAS0B,qBAAqBvB,EAAOsB,WAAa,UACtDxB,EAAUyB,qBAAqBvB,EAAOsB,WAAa,WACnD,qBAAqBR,KAAKO,GAAQ,MAClC,iBAAiBP,KAAKO,IACtB,iBAAiBP,KAAKO,IACtB,uBAAuBP,KAAKO,IAC5B,uCAAuCP,KAAKO,IAC5C,YAAYP,KAAKO,GAJa,SAK9B,UACN,CACA,OAAOD,CACT,EACAI,aAAc,CACZC,cAAe,CAACC,KAAM,O","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/eiffel.js"],"sourcesContent":["function wordObj(words) {\n var o = {};\n for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;\n return o;\n}\nvar keywords = wordObj([\n 'note',\n 'across',\n 'when',\n 'variant',\n 'until',\n 'unique',\n 'undefine',\n 'then',\n 'strip',\n 'select',\n 'retry',\n 'rescue',\n 'require',\n 'rename',\n 'reference',\n 'redefine',\n 'prefix',\n 'once',\n 'old',\n 'obsolete',\n 'loop',\n 'local',\n 'like',\n 'is',\n 'inspect',\n 'infix',\n 'include',\n 'if',\n 'frozen',\n 'from',\n 'external',\n 'export',\n 'ensure',\n 'end',\n 'elseif',\n 'else',\n 'do',\n 'creation',\n 'create',\n 'check',\n 'alias',\n 'agent',\n 'separate',\n 'invariant',\n 'inherit',\n 'indexing',\n 'feature',\n 'expanded',\n 'deferred',\n 'class',\n 'Void',\n 'True',\n 'Result',\n 'Precursor',\n 'False',\n 'Current',\n 'create',\n 'attached',\n 'detachable',\n 'as',\n 'and',\n 'implies',\n 'not',\n 'or'\n]);\nvar operators = wordObj([\":=\", \"and then\",\"and\", \"or\",\"<<\",\">>\"]);\n\nfunction chain(newtok, stream, state) {\n state.tokenize.push(newtok);\n return newtok(stream, state);\n}\n\nfunction tokenBase(stream, state) {\n if (stream.eatSpace()) return null;\n var ch = stream.next();\n if (ch == '\"'||ch == \"'\") {\n return chain(readQuoted(ch, \"string\"), stream, state);\n } else if (ch == \"-\"&&stream.eat(\"-\")) {\n stream.skipToEnd();\n return \"comment\";\n } else if (ch == \":\"&&stream.eat(\"=\")) {\n return \"operator\";\n } else if (/[0-9]/.test(ch)) {\n stream.eatWhile(/[xXbBCc0-9\\.]/);\n stream.eat(/[\\?\\!]/);\n return \"variable\";\n } else if (/[a-zA-Z_0-9]/.test(ch)) {\n stream.eatWhile(/[a-zA-Z_0-9]/);\n stream.eat(/[\\?\\!]/);\n return \"variable\";\n } else if (/[=+\\-\\/*^%<>~]/.test(ch)) {\n stream.eatWhile(/[=+\\-\\/*^%<>~]/);\n return \"operator\";\n } else {\n return null;\n }\n}\n\nfunction readQuoted(quote, style, unescaped) {\n return function(stream, state) {\n var escaped = false, ch;\n while ((ch = stream.next()) != null) {\n if (ch == quote && (unescaped || !escaped)) {\n state.tokenize.pop();\n break;\n }\n escaped = !escaped && ch == \"%\";\n }\n return style;\n };\n}\n\nexport const eiffel = {\n name: \"eiffel\",\n startState: function() {\n return {tokenize: [tokenBase]};\n },\n\n token: function(stream, state) {\n var style = state.tokenize[state.tokenize.length-1](stream, state);\n if (style == \"variable\") {\n var word = stream.current();\n style = keywords.propertyIsEnumerable(stream.current()) ? \"keyword\"\n : operators.propertyIsEnumerable(stream.current()) ? \"operator\"\n : /^[A-Z][A-Z_0-9]*$/g.test(word) ? \"tag\"\n : /^0[bB][0-1]+$/g.test(word) ? \"number\"\n : /^0[cC][0-7]+$/g.test(word) ? \"number\"\n : /^0[xX][a-fA-F0-9]+$/g.test(word) ? \"number\"\n : /^([0-9]+\\.[0-9]*)|([0-9]*\\.[0-9]+)$/g.test(word) ? \"number\"\n : /^[0-9]+$/g.test(word) ? \"number\"\n : \"variable\";\n }\n return style;\n },\n languageData: {\n commentTokens: {line: \"--\"}\n }\n};\n\n"],"names":["wordObj","words","o","i","e","length","keywords","operators","tokenBase","stream","state","eatSpace","quote","ch","next","newtok","tokenize","push","chain","escaped","pop","eat","skipToEnd","test","eatWhile","eiffel","name","startState","token","style","word","current","propertyIsEnumerable","languageData","commentTokens","line"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/5395.index.js b/book/_build/html/_static/5395.index.js
new file mode 100644
index 0000000..f06c5d7
--- /dev/null
+++ b/book/_build/html/_static/5395.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[5395],{25395:(e,t,n)=>{n.r(t),n.d(t,{sas:()=>l});var r={},s={eq:"operator",lt:"operator",le:"operator",gt:"operator",ge:"operator",in:"operator",ne:"operator",or:"operator"},a=/(<=|>=|!=|<>)/,o=/[=\(:\),{}.*<>+\-\/^\[\]]/;function i(e,t,n){if(n)for(var s=t.split(" "),a=0;a=|!=|<>)/;\nvar isSingleOperatorChar = /[=\\(:\\),{}.*<>+\\-\\/^\\[\\]]/;\n\n// Takes a string of words separated by spaces and adds them as\n// keys with the value of the first argument 'style'\nfunction define(style, string, context) {\n if (context) {\n var split = string.split(' ');\n for (var i = 0; i < split.length; i++) {\n words[split[i]] = {style: style, state: context};\n }\n }\n}\n//datastep\ndefine('def', 'stack pgm view source debug nesting nolist', ['inDataStep']);\ndefine('def', 'if while until for do do; end end; then else cancel', ['inDataStep']);\ndefine('def', 'label format _n_ _error_', ['inDataStep']);\ndefine('def', 'ALTER BUFNO BUFSIZE CNTLLEV COMPRESS DLDMGACTION ENCRYPT ENCRYPTKEY EXTENDOBSCOUNTER GENMAX GENNUM INDEX LABEL OBSBUF OUTREP PW PWREQ READ REPEMPTY REPLACE REUSE ROLE SORTEDBY SPILL TOBSNO TYPE WRITE FILECLOSE FIRSTOBS IN OBS POINTOBS WHERE WHEREUP IDXNAME IDXWHERE DROP KEEP RENAME', ['inDataStep']);\ndefine('def', 'filevar finfo finv fipname fipnamel fipstate first firstobs floor', ['inDataStep']);\ndefine('def', 'varfmt varinfmt varlabel varlen varname varnum varray varrayx vartype verify vformat vformatd vformatdx vformatn vformatnx vformatw vformatwx vformatx vinarray vinarrayx vinformat vinformatd vinformatdx vinformatn vinformatnx vinformatw vinformatwx vinformatx vlabel vlabelx vlength vlengthx vname vnamex vnferr vtype vtypex weekday', ['inDataStep']);\ndefine('def', 'zipfips zipname zipnamel zipstate', ['inDataStep']);\ndefine('def', 'put putc putn', ['inDataStep']);\ndefine('builtin', 'data run', ['inDataStep']);\n\n\n//proc\ndefine('def', 'data', ['inProc']);\n\n// flow control for macros\ndefine('def', '%if %end %end; %else %else; %do %do; %then', ['inMacro']);\n\n//everywhere\ndefine('builtin', 'proc run; quit; libname filename %macro %mend option options', ['ALL']);\n\ndefine('def', 'footnote title libname ods', ['ALL']);\ndefine('def', '%let %put %global %sysfunc %eval ', ['ALL']);\n// automatic macro variables http://support.sas.com/documentation/cdl/en/mcrolref/61885/HTML/default/viewer.htm#a003167023.htm\ndefine('variable', '&sysbuffr &syscc &syscharwidth &syscmd &sysdate &sysdate9 &sysday &sysdevic &sysdmg &sysdsn &sysencoding &sysenv &syserr &syserrortext &sysfilrc &syshostname &sysindex &sysinfo &sysjobid &syslast &syslckrc &syslibrc &syslogapplname &sysmacroname &sysmenv &sysmsg &sysncpu &sysodspath &sysparm &syspbuff &sysprocessid &sysprocessname &sysprocname &sysrc &sysscp &sysscpl &sysscpl &syssite &sysstartid &sysstartname &systcpiphostname &systime &sysuserid &sysver &sysvlong &sysvlong4 &syswarningtext', ['ALL']);\n\n//footnote[1-9]? title[1-9]?\n\n//options statement\ndefine('def', 'source2 nosource2 page pageno pagesize', ['ALL']);\n\n//proc and datastep\ndefine('def', '_all_ _character_ _cmd_ _freq_ _i_ _infile_ _last_ _msg_ _null_ _numeric_ _temporary_ _type_ abort abs addr adjrsq airy alpha alter altlog altprint and arcos array arsin as atan attrc attrib attrn authserver autoexec awscontrol awsdef awsmenu awsmenumerge awstitle backward band base betainv between blocksize blshift bnot bor brshift bufno bufsize bxor by byerr byline byte calculated call cards cards4 catcache cbufno cdf ceil center cexist change chisq cinv class cleanup close cnonct cntllev coalesce codegen col collate collin column comamid comaux1 comaux2 comdef compbl compound compress config continue convert cos cosh cpuid create cross crosstab css curobs cv daccdb daccdbsl daccsl daccsyd dacctab dairy datalines datalines4 datejul datepart datetime day dbcslang dbcstype dclose ddfm ddm delete delimiter depdb depdbsl depsl depsyd deptab dequote descending descript design= device dflang dhms dif digamma dim dinfo display distinct dkricond dkrocond dlm dnum do dopen doptname doptnum dread drop dropnote dsname dsnferr echo else emaildlg emailid emailpw emailserver emailsys encrypt end endsas engine eof eov erf erfc error errorcheck errors exist exp fappend fclose fcol fdelete feedback fetch fetchobs fexist fget file fileclose fileexist filefmt filename fileref fmterr fmtsearch fnonct fnote font fontalias fopen foptname foptnum force formatted formchar formdelim formdlim forward fpoint fpos fput fread frewind frlen from fsep fuzz fwrite gaminv gamma getoption getvarc getvarn go goto group gwindow hbar hbound helpenv helploc hms honorappearance hosthelp hostprint hour hpct html hvar ibessel ibr id if index indexc indexw initcmd initstmt inner input inputc inputn inr insert int intck intnx into intrr invaliddata irr is jbessel join juldate keep kentb kurtosis label lag last lbound leave left length levels lgamma lib library libref line linesize link list log log10 log2 logpdf logpmf logsdf lostcard lowcase lrecl ls macro macrogen maps mautosource max maxdec maxr mdy mean measures median memtype merge merror min minute missing missover mlogic mod mode model modify month mopen mort mprint mrecall msglevel msymtabmax mvarsize myy n nest netpv new news nmiss no nobatch nobs nocaps nocardimage nocenter nocharcode nocmdmac nocol nocum nodate nodbcs nodetails nodmr nodms nodmsbatch nodup nodupkey noduplicates noechoauto noequals noerrorabend noexitwindows nofullstimer noicon noimplmac noint nolist noloadlist nomiss nomlogic nomprint nomrecall nomsgcase nomstored nomultenvappl nonotes nonumber noobs noovp nopad nopercent noprint noprintinit normal norow norsasuser nosetinit nosplash nosymbolgen note notes notitle notitles notsorted noverbose noxsync noxwait npv null number numkeys nummousekeys nway obs on open order ordinal otherwise out outer outp= output over ovp p(1 5 10 25 50 75 90 95 99) pad pad2 paired parm parmcards path pathdll pathname pdf peek peekc pfkey pmf point poisson poke position printer probbeta probbnml probchi probf probgam probhypr probit probnegb probnorm probsig probt procleave prt ps pw pwreq qtr quote r ranbin rancau random ranexp rangam range ranks rannor ranpoi rantbl rantri ranuni rcorr read recfm register regr remote remove rename repeat repeated replace resolve retain return reuse reverse rewind right round rsquare rtf rtrace rtraceloc s s2 samploc sasautos sascontrol sasfrscr sasmsg sasmstore sasscript sasuser saving scan sdf second select selection separated seq serror set setcomm setot sign simple sin sinh siteinfo skewness skip sle sls sortedby sortpgm sortseq sortsize soundex spedis splashlocation split spool sqrt start std stderr stdin stfips stimer stname stnamel stop stopover sub subgroup subpopn substr sum sumwgt symbol symbolgen symget symput sysget sysin sysleave sysmsg sysparm sysprint sysprintfont sysprod sysrc system t table tables tan tanh tapeclose tbufsize terminal test then timepart tinv tnonct to today tol tooldef totper transformout translate trantab tranwrd trigamma trim trimn trunc truncover type unformatted uniform union until upcase update user usericon uss validate value var weight when where while wincharset window work workinit workterm write wsum xsync xwait yearcutoff yes yyq min max', ['inDataStep', 'inProc']);\ndefine('operator', 'and not ', ['inDataStep', 'inProc']);\n\n// Main function\nfunction tokenize(stream, state) {\n // Finally advance the stream\n var ch = stream.next();\n\n // BLOCKCOMMENT\n if (ch === '/' && stream.eat('*')) {\n state.continueComment = true;\n return \"comment\";\n } else if (state.continueComment === true) { // in comment block\n //comment ends at the beginning of the line\n if (ch === '*' && stream.peek() === '/') {\n stream.next();\n state.continueComment = false;\n } else if (stream.skipTo('*')) { //comment is potentially later in line\n stream.skipTo('*');\n stream.next();\n if (stream.eat('/'))\n state.continueComment = false;\n } else {\n stream.skipToEnd();\n }\n return \"comment\";\n }\n\n if (ch == \"*\" && stream.column() == stream.indentation()) {\n stream.skipToEnd()\n return \"comment\"\n }\n\n // DoubleOperator match\n var doubleOperator = ch + stream.peek();\n\n if ((ch === '\"' || ch === \"'\") && !state.continueString) {\n state.continueString = ch\n return \"string\"\n } else if (state.continueString) {\n if (state.continueString == ch) {\n state.continueString = null;\n } else if (stream.skipTo(state.continueString)) {\n // quote found on this line\n stream.next();\n state.continueString = null;\n } else {\n stream.skipToEnd();\n }\n return \"string\";\n } else if (state.continueString !== null && stream.eol()) {\n stream.skipTo(state.continueString) || stream.skipToEnd();\n return \"string\";\n } else if (/[\\d\\.]/.test(ch)) { //find numbers\n if (ch === \".\")\n stream.match(/^[0-9]+([eE][\\-+]?[0-9]+)?/);\n else if (ch === \"0\")\n stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/);\n else\n stream.match(/^[0-9]*\\.?[0-9]*([eE][\\-+]?[0-9]+)?/);\n return \"number\";\n } else if (isDoubleOperatorChar.test(ch + stream.peek())) { // TWO SYMBOL TOKENS\n stream.next();\n return \"operator\";\n } else if (isDoubleOperatorSym.hasOwnProperty(doubleOperator)) {\n stream.next();\n if (stream.peek() === ' ')\n return isDoubleOperatorSym[doubleOperator.toLowerCase()];\n } else if (isSingleOperatorChar.test(ch)) { // SINGLE SYMBOL TOKENS\n return \"operator\";\n }\n\n // Matches one whole word -- even if the word is a character\n var word;\n if (stream.match(/[%&;\\w]+/, false) != null) {\n word = ch + stream.match(/[%&;\\w]+/, true);\n if (/&/.test(word)) return 'variable'\n } else {\n word = ch;\n }\n // the word after DATA PROC or MACRO\n if (state.nextword) {\n stream.match(/[\\w]+/);\n // match memname.libname\n if (stream.peek() === '.') stream.skipTo(' ');\n state.nextword = false;\n return 'variableName.special';\n }\n\n word = word.toLowerCase()\n // Are we in a DATA Step?\n if (state.inDataStep) {\n if (word === 'run;' || stream.match(/run\\s;/)) {\n state.inDataStep = false;\n return 'builtin';\n }\n // variable formats\n if ((word) && stream.next() === '.') {\n //either a format or libname.memname\n if (/\\w/.test(stream.peek())) return 'variableName.special';\n else return 'variable';\n }\n // do we have a DATA Step keyword\n if (word && words.hasOwnProperty(word) &&\n (words[word].state.indexOf(\"inDataStep\") !== -1 ||\n words[word].state.indexOf(\"ALL\") !== -1)) {\n //backup to the start of the word\n if (stream.start < stream.pos)\n stream.backUp(stream.pos - stream.start);\n //advance the length of the word and return\n for (var i = 0; i < word.length; ++i) stream.next();\n return words[word].style;\n }\n }\n // Are we in an Proc statement?\n if (state.inProc) {\n if (word === 'run;' || word === 'quit;') {\n state.inProc = false;\n return 'builtin';\n }\n // do we have a proc keyword\n if (word && words.hasOwnProperty(word) &&\n (words[word].state.indexOf(\"inProc\") !== -1 ||\n words[word].state.indexOf(\"ALL\") !== -1)) {\n stream.match(/[\\w]+/);\n return words[word].style;\n }\n }\n // Are we in a Macro statement?\n if (state.inMacro) {\n if (word === '%mend') {\n if (stream.peek() === ';') stream.next();\n state.inMacro = false;\n return 'builtin';\n }\n if (word && words.hasOwnProperty(word) &&\n (words[word].state.indexOf(\"inMacro\") !== -1 ||\n words[word].state.indexOf(\"ALL\") !== -1)) {\n stream.match(/[\\w]+/);\n return words[word].style;\n }\n\n return 'atom';\n }\n // Do we have Keywords specific words?\n if (word && words.hasOwnProperty(word)) {\n // Negates the initial next()\n stream.backUp(1);\n // Actually move the stream\n stream.match(/[\\w]+/);\n if (word === 'data' && /=/.test(stream.peek()) === false) {\n state.inDataStep = true;\n state.nextword = true;\n return 'builtin';\n }\n if (word === 'proc') {\n state.inProc = true;\n state.nextword = true;\n return 'builtin';\n }\n if (word === '%macro') {\n state.inMacro = true;\n state.nextword = true;\n return 'builtin';\n }\n if (/title[1-9]/.test(word)) return 'def';\n\n if (word === 'footnote') {\n stream.eat(/[1-9]/);\n return 'def';\n }\n\n // Returns their value as state in the prior define methods\n if (state.inDataStep === true && words[word].state.indexOf(\"inDataStep\") !== -1)\n return words[word].style;\n if (state.inProc === true && words[word].state.indexOf(\"inProc\") !== -1)\n return words[word].style;\n if (state.inMacro === true && words[word].state.indexOf(\"inMacro\") !== -1)\n return words[word].style;\n if (words[word].state.indexOf(\"ALL\") !== -1)\n return words[word].style;\n return null;\n }\n // Unrecognized syntax\n return null;\n}\n\nexport const sas = {\n name: \"sas\",\n startState: function () {\n return {\n inDataStep: false,\n inProc: false,\n inMacro: false,\n nextword: false,\n continueString: null,\n continueComment: false\n };\n },\n token: function (stream, state) {\n // Strip the spaces, but regex will account for them either way\n if (stream.eatSpace()) return null;\n // Go through the main process\n return tokenize(stream, state);\n },\n\n languageData: {\n commentTokens: {block: {open: \"/*\", close: \"*/\"}}\n }\n};\n"],"names":["words","isDoubleOperatorSym","eq","lt","le","gt","ge","ne","or","isDoubleOperatorChar","isSingleOperatorChar","define","style","string","context","split","i","length","state","sas","name","startState","inDataStep","inProc","inMacro","nextword","continueString","continueComment","token","stream","eatSpace","ch","next","eat","peek","skipTo","skipToEnd","column","indentation","word","doubleOperator","eol","test","match","hasOwnProperty","toLowerCase","indexOf","start","pos","backUp","tokenize","languageData","commentTokens","block","open","close"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/545.index.js b/book/_build/html/_static/545.index.js
new file mode 100644
index 0000000..da404b4
--- /dev/null
+++ b/book/_build/html/_static/545.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[545],{60545:(t,e,n)=>{n.r(e),n.d(e,{shell:()=>k});var r={};function s(t,e){for(var n=0;n1&&t.eat("$");var n=t.next();return/['"({]/.test(n)?(e.tokens[0]=f(n,"("==n?"quote":"{"==n?"def":"string"),h(t,e)):(/\d/.test(n)||t.eatWhile(/\w/),e.tokens.shift(),"def")};function h(t,e){return(e.tokens[0]||a)(t,e)}const k={name:"shell",startState:function(){return{tokens:[]}},token:function(t,e){return h(t,e)},languageData:{autocomplete:i.concat(o,u),closeBrackets:{brackets:["(","[","{","'",'"',"`"]},commentTokens:{line:"#"}}}}}]);
+//# sourceMappingURL=545.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/545.index.js.map b/book/_build/html/_static/545.index.js.map
new file mode 100644
index 0000000..128433e
--- /dev/null
+++ b/book/_build/html/_static/545.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"545.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/shell.js"],"sourcesContent":["var words = {};\nfunction define(style, dict) {\n for(var i = 0; i < dict.length; i++) {\n words[dict[i]] = style;\n }\n};\n\nvar commonAtoms = [\"true\", \"false\"];\nvar commonKeywords = [\"if\", \"then\", \"do\", \"else\", \"elif\", \"while\", \"until\", \"for\", \"in\", \"esac\", \"fi\",\n \"fin\", \"fil\", \"done\", \"exit\", \"set\", \"unset\", \"export\", \"function\"];\nvar commonCommands = [\"ab\", \"awk\", \"bash\", \"beep\", \"cat\", \"cc\", \"cd\", \"chown\", \"chmod\", \"chroot\", \"clear\",\n \"cp\", \"curl\", \"cut\", \"diff\", \"echo\", \"find\", \"gawk\", \"gcc\", \"get\", \"git\", \"grep\", \"hg\", \"kill\", \"killall\",\n \"ln\", \"ls\", \"make\", \"mkdir\", \"openssl\", \"mv\", \"nc\", \"nl\", \"node\", \"npm\", \"ping\", \"ps\", \"restart\", \"rm\",\n \"rmdir\", \"sed\", \"service\", \"sh\", \"shopt\", \"shred\", \"source\", \"sort\", \"sleep\", \"ssh\", \"start\", \"stop\",\n \"su\", \"sudo\", \"svn\", \"tee\", \"telnet\", \"top\", \"touch\", \"vi\", \"vim\", \"wall\", \"wc\", \"wget\", \"who\", \"write\",\n \"yes\", \"zsh\"];\n\ndefine('atom', commonAtoms);\ndefine('keyword', commonKeywords);\ndefine('builtin', commonCommands);\n\nfunction tokenBase(stream, state) {\n if (stream.eatSpace()) return null;\n\n var sol = stream.sol();\n var ch = stream.next();\n\n if (ch === '\\\\') {\n stream.next();\n return null;\n }\n if (ch === '\\'' || ch === '\"' || ch === '`') {\n state.tokens.unshift(tokenString(ch, ch === \"`\" ? \"quote\" : \"string\"));\n return tokenize(stream, state);\n }\n if (ch === '#') {\n if (sol && stream.eat('!')) {\n stream.skipToEnd();\n return 'meta'; // 'comment'?\n }\n stream.skipToEnd();\n return 'comment';\n }\n if (ch === '$') {\n state.tokens.unshift(tokenDollar);\n return tokenize(stream, state);\n }\n if (ch === '+' || ch === '=') {\n return 'operator';\n }\n if (ch === '-') {\n stream.eat('-');\n stream.eatWhile(/\\w/);\n return 'attribute';\n }\n if (ch == \"<\") {\n if (stream.match(\"<<\")) return \"operator\"\n var heredoc = stream.match(/^<-?\\s*(?:['\"]([^'\"]*)['\"]|([^'\"\\s]*))/)\n if (heredoc) {\n state.tokens.unshift(tokenHeredoc(heredoc[1] || heredoc[2]))\n return 'string.special'\n }\n }\n if (/\\d/.test(ch)) {\n stream.eatWhile(/\\d/);\n if(stream.eol() || !/\\w/.test(stream.peek())) {\n return 'number';\n }\n }\n stream.eatWhile(/[\\w-]/);\n var cur = stream.current();\n if (stream.peek() === '=' && /\\w+/.test(cur)) return 'def';\n return words.hasOwnProperty(cur) ? words[cur] : null;\n}\n\nfunction tokenString(quote, style) {\n var close = quote == \"(\" ? \")\" : quote == \"{\" ? \"}\" : quote\n return function(stream, state) {\n var next, escaped = false;\n while ((next = stream.next()) != null) {\n if (next === close && !escaped) {\n state.tokens.shift();\n break;\n } else if (next === '$' && !escaped && quote !== \"'\" && stream.peek() != close) {\n escaped = true;\n stream.backUp(1);\n state.tokens.unshift(tokenDollar);\n break;\n } else if (!escaped && quote !== close && next === quote) {\n state.tokens.unshift(tokenString(quote, style))\n return tokenize(stream, state)\n } else if (!escaped && /['\"]/.test(next) && !/['\"]/.test(quote)) {\n state.tokens.unshift(tokenStringStart(next, \"string\"));\n stream.backUp(1);\n break;\n }\n escaped = !escaped && next === '\\\\';\n }\n return style;\n };\n};\n\nfunction tokenStringStart(quote, style) {\n return function(stream, state) {\n state.tokens[0] = tokenString(quote, style)\n stream.next()\n return tokenize(stream, state)\n }\n}\n\nvar tokenDollar = function(stream, state) {\n if (state.tokens.length > 1) stream.eat('$');\n var ch = stream.next()\n if (/['\"({]/.test(ch)) {\n state.tokens[0] = tokenString(ch, ch == \"(\" ? \"quote\" : ch == \"{\" ? \"def\" : \"string\");\n return tokenize(stream, state);\n }\n if (!/\\d/.test(ch)) stream.eatWhile(/\\w/);\n state.tokens.shift();\n return 'def';\n};\n\nfunction tokenHeredoc(delim) {\n return function(stream, state) {\n if (stream.sol() && stream.string == delim) state.tokens.shift()\n stream.skipToEnd()\n return \"string.special\"\n }\n}\n\nfunction tokenize(stream, state) {\n return (state.tokens[0] || tokenBase) (stream, state);\n};\n\nexport const shell = {\n name: \"shell\",\n startState: function() {return {tokens:[]};},\n token: function(stream, state) {\n return tokenize(stream, state);\n },\n languageData: {\n autocomplete: commonAtoms.concat(commonKeywords, commonCommands),\n closeBrackets: {brackets: [\"(\", \"[\", \"{\", \"'\", '\"', \"`\"]},\n commentTokens: {line: \"#\"}\n }\n};\n"],"names":["words","define","style","dict","i","length","commonAtoms","commonKeywords","commonCommands","tokenBase","stream","state","eatSpace","delim","sol","ch","next","tokens","unshift","tokenString","tokenize","eat","skipToEnd","tokenDollar","eatWhile","match","heredoc","string","shift","test","eol","peek","cur","current","hasOwnProperty","quote","close","escaped","backUp","tokenStringStart","shell","name","startState","token","languageData","autocomplete","concat","closeBrackets","brackets","commentTokens","line"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/5571.index.js b/book/_build/html/_static/5571.index.js
new file mode 100644
index 0000000..65f04f9
--- /dev/null
+++ b/book/_build/html/_static/5571.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[5571],{55571:(e,t,n)=>{function r(e,t,n,r,a,o){this.indented=e,this.column=t,this.type=n,this.info=r,this.align=a,this.prev=o}function a(e,t,n,a){var o=e.indented;return e.context&&"statement"==e.context.type&&"statement"!=n&&(o=e.context.indented),e.context=new r(o,t,n,a,null,e.context)}function o(e){var t=e.context.type;return")"!=t&&"]"!=t&&"}"!=t||(e.indented=e.context.indented),e.context=e.context.prev}function i(e,t,n){return"variable"==t.prevToken||"type"==t.prevToken||!!/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(e.string.slice(0,n))||!(!t.typeAtEndOfLine||e.column()!=e.indentation())||void 0}function l(e){for(;;){if(!e||"top"==e.type)return!0;if("}"==e.type&&"namespace"!=e.prev.info)return!1;e=e.prev}}function s(e){var t,n,s=e.statementIndentUnit,c=e.dontAlignCalls,d=e.keywords||{},f=e.types||{},p=e.builtin||{},m=e.blockKeywords||{},h=e.defKeywords||{},y=e.atoms||{},g=e.hooks||{},k=e.multiLineStrings,b=!1!==e.indentStatements,v=!1!==e.indentSwitch,w=e.namespaceSeparator,_=e.isPunctuationChar||/[\[\]{}\(\),;\:\.]/,x=e.numberStart||/[\d\.]/,S=e.number||/^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)(u|ll?|l|f)?/i,T=e.isOperatorChar||/[+\-*&%=<>!?|\/]/,N=e.isIdentifierChar||/[\w\$_\xa1-\uffff]/,C=e.isReservedIdentifier||!1;function I(e,r){var a,o=e.next();if(g[o]){var i=g[o](e,r);if(!1!==i)return i}if('"'==o||"'"==o)return r.tokenize=(a=o,function(e,t){for(var n,r=!1,o=!1;null!=(n=e.next());){if(n==a&&!r){o=!0;break}r=!r&&"\\"==n}return(o||!r&&!k)&&(t.tokenize=null),"string"}),r.tokenize(e,r);if(x.test(o)){if(e.backUp(1),e.match(S))return"number";e.next()}if(_.test(o))return t=o,null;if("/"==o){if(e.eat("*"))return r.tokenize=D,D(e,r);if(e.eat("/"))return e.skipToEnd(),"comment"}if(T.test(o)){for(;!e.match(/^\/[\/*]/,!1)&&e.eat(T););return"operator"}if(e.eatWhile(N),w)for(;e.match(w);)e.eatWhile(N);var l=e.current();return u(d,l)?(u(m,l)&&(t="newstatement"),u(h,l)&&(n=!0),"keyword"):u(f,l)?"type":u(p,l)||C&&C(l)?(u(m,l)&&(t="newstatement"),"builtin"):u(y,l)?"atom":"variable"}function D(e,t){for(var n,r=!1;n=e.next();){if("/"==n&&r){t.tokenize=null;break}r="*"==n}return"comment"}function z(t,n){e.typeFirstDefinitions&&t.eol()&&l(n.context)&&(n.typeAtEndOfLine=i(t,n,t.pos))}return{name:e.name,startState:function(e){return{tokenize:null,context:new r(-e,0,"top",null,!1),indented:0,startOfLine:!0,prevToken:null}},token:function(r,s){var c=s.context;if(r.sol()&&(null==c.align&&(c.align=!1),s.indented=r.indentation(),s.startOfLine=!0),r.eatSpace())return z(r,s),null;t=n=null;var u=(s.tokenize||I)(r,s);if("comment"==u||"meta"==u)return u;if(null==c.align&&(c.align=!0),";"==t||":"==t||","==t&&r.match(/^\s*(?:\/\/.*)?$/,!1))for(;"statement"==s.context.type;)o(s);else if("{"==t)a(s,r.column(),"}");else if("["==t)a(s,r.column(),"]");else if("("==t)a(s,r.column(),")");else if("}"==t){for(;"statement"==c.type;)c=o(s);for("}"==c.type&&(c=o(s));"statement"==c.type;)c=o(s)}else t==c.type?o(s):b&&(("}"==c.type||"top"==c.type)&&";"!=t||"statement"==c.type&&"newstatement"==t)&&a(s,r.column(),"statement",r.current());if("variable"==u&&("def"==s.prevToken||e.typeFirstDefinitions&&i(r,s,r.start)&&l(s.context)&&r.match(/^\s*\(/,!1))&&(u="def"),g.token){var d=g.token(r,s,u);void 0!==d&&(u=d)}return"def"==u&&!1===e.styleDefs&&(u="variable"),s.startOfLine=!1,s.prevToken=n?"def":u||t,z(r,s),u},indent:function(t,n,r){if(t.tokenize!=I&&null!=t.tokenize||t.typeAtEndOfLine&&l(t.context))return null;var a=t.context,o=n&&n.charAt(0),i=o==a.type;if("statement"==a.type&&"}"==o&&(a=a.prev),e.dontIndentStatements)for(;"statement"==a.type&&e.dontIndentStatements.test(a.info);)a=a.prev;if(g.indent){var u=g.indent(t,a,n,r.unit);if("number"==typeof u)return u}var d=a.prev&&"switch"==a.prev.info;if(e.allmanIndentation&&/[{(]/.test(o)){for(;"top"!=a.type&&"}"!=a.type;)a=a.prev;return a.indented}return"statement"==a.type?a.indented+("{"==o?0:s||r.unit):!a.align||c&&")"==a.type?")"!=a.type||i?a.indented+(i?0:r.unit)+(i||!d||/^(?:case|default)\b/.test(n)?0:r.unit):a.indented+(s||r.unit):a.column+(i?0:1)},languageData:{indentOnInput:v?/^\s*(?:case .*?:|default:|\{\}?|\})$/:/^\s*[{}]$/,commentTokens:{line:"//",block:{open:"/*",close:"*/"}},autocomplete:Object.keys(d).concat(Object.keys(f)).concat(Object.keys(p)).concat(Object.keys(y)),...e.languageData}}}function c(e){for(var t={},n=e.split(" "),r=0;rD,ceylon:()=>q,clike:()=>s,cpp:()=>z,csharp:()=>M,dart:()=>X,java:()=>L,kotlin:()=>R,nesC:()=>j,objectiveC:()=>A,objectiveCpp:()=>U,scala:()=>P,shader:()=>O,squirrel:()=>$});var d="auto if break case register continue return default do sizeof static else struct switch extern typedef union for goto while enum const volatile inline restrict asm fortran",f="alignas alignof and and_eq audit axiom bitand bitor catch class compl concept constexpr const_cast decltype delete dynamic_cast explicit export final friend import module mutable namespace new noexcept not not_eq operator or or_eq override private protected public reinterpret_cast requires static_assert static_cast template this thread_local throw try typeid typename using virtual xor xor_eq",p="bycopy byref in inout oneway out self super atomic nonatomic retain copy readwrite readonly strong weak assign typeof nullable nonnull null_resettable _cmd @interface @implementation @end @protocol @encode @property @synthesize @dynamic @class @public @package @private @protected @required @optional @try @catch @finally @import @selector @encode @defs @synchronized @autoreleasepool @compatibility_alias @available",m="FOUNDATION_EXPORT FOUNDATION_EXTERN NS_INLINE NS_FORMAT_FUNCTION NS_RETURNS_RETAINEDNS_ERROR_ENUM NS_RETURNS_NOT_RETAINED NS_RETURNS_INNER_POINTER NS_DESIGNATED_INITIALIZER NS_ENUM NS_OPTIONS NS_REQUIRES_NIL_TERMINATION NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_SWIFT_NAME NS_REFINED_FOR_SWIFT",h=c("int long char short double float unsigned signed void bool"),y=c("SEL instancetype id Class Protocol BOOL");function g(e){return u(h,e)||/.+_t$/.test(e)}function k(e){return g(e)||u(y,e)}var b="case do else for if switch while struct enum union",v="struct enum union";function w(e,t){if(!t.startOfLine)return!1;for(var n,r=null;n=e.peek();){if("\\"==n&&e.match(/^.$/)){r=w;break}if("/"==n&&e.match(/^\/[\/\*]/,!1))break;e.next()}return t.tokenize=r,"meta"}function _(e,t){return"type"==t.prevToken&&"type"}function x(e){return!(!e||e.length<2||"_"!=e[0]||"_"!=e[1]&&e[1]===e[1].toLowerCase())}function S(e){return e.eatWhile(/[\w\.']/),"number"}function T(e,t){if(e.backUp(1),e.match(/^(?:R|u8R|uR|UR|LR)/)){var n=e.match(/^"([^\s\\()]{0,16})\(/);return!!n&&(t.cpp11RawStringDelim=n[1],t.tokenize=I,I(e,t))}return e.match(/^(?:u8|u|U|L)/)?!!e.match(/^["']/,!1)&&"string":(e.next(),!1)}function N(e){var t=/(\w+)::~?(\w+)$/.exec(e);return t&&t[1]==t[2]}function C(e,t){for(var n;null!=(n=e.next());)if('"'==n&&!e.eat('"')){t.tokenize=null;break}return"string"}function I(e,t){var n=t.cpp11RawStringDelim.replace(/[^\w\s]/g,"\\$&");return e.match(new RegExp(".*?\\)"+n+'"'))?t.tokenize=null:e.skipToEnd(),"string"}const D=s({name:"c",keywords:c(d),types:g,blockKeywords:c(b),defKeywords:c(v),typeFirstDefinitions:!0,atoms:c("NULL true false"),isReservedIdentifier:x,hooks:{"#":w,"*":_}}),z=s({name:"cpp",keywords:c(d+" "+f),types:g,blockKeywords:c(b+" class try catch"),defKeywords:c(v+" class namespace"),typeFirstDefinitions:!0,atoms:c("true false NULL nullptr"),dontIndentStatements:/^template$/,isIdentifierChar:/[\w\$_~\xa1-\uffff]/,isReservedIdentifier:x,hooks:{"#":w,"*":_,u:T,U:T,L:T,R:T,0:S,1:S,2:S,3:S,4:S,5:S,6:S,7:S,8:S,9:S,token:function(e,t,n){if("variable"==n&&"("==e.peek()&&(";"==t.prevToken||null==t.prevToken||"}"==t.prevToken)&&N(e.current()))return"def"}},namespaceSeparator:"::"}),L=s({name:"java",keywords:c("abstract assert break case catch class const continue default do else enum extends final finally for goto if implements import instanceof interface native new package private protected public return static strictfp super switch synchronized this throw throws transient try volatile while @interface"),types:c("var byte short int long float double boolean char void Boolean Byte Character Double Float Integer Long Number Object Short String StringBuffer StringBuilder Void"),blockKeywords:c("catch class do else finally for if switch try while"),defKeywords:c("class interface enum @interface"),typeFirstDefinitions:!0,atoms:c("true false null"),number:/^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+\.?\d*|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,hooks:{"@":function(e){return!e.match("interface",!1)&&(e.eatWhile(/[\w\$_]/),"meta")},'"':function(e,t){return!!e.match(/""$/)&&(t.tokenize=E,t.tokenize(e,t))}}}),M=s({name:"csharp",keywords:c("abstract as async await base break case catch checked class const continue default delegate do else enum event explicit extern finally fixed for foreach goto if implicit in init interface internal is lock namespace new operator out override params private protected public readonly record ref required return sealed sizeof stackalloc static struct switch this throw try typeof unchecked unsafe using virtual void volatile while add alias ascending descending dynamic from get global group into join let orderby partial remove select set value var yield"),types:c("Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32 UInt64 bool byte char decimal double short int long object sbyte float string ushort uint ulong"),blockKeywords:c("catch class do else finally for foreach if struct switch try while"),defKeywords:c("class interface namespace record struct var"),typeFirstDefinitions:!0,atoms:c("true false null"),hooks:{"@":function(e,t){return e.eat('"')?(t.tokenize=C,C(e,t)):(e.eatWhile(/[\w\$_]/),"meta")}}});function E(e,t){for(var n=!1;!e.eol();){if(!n&&e.match('"""')){t.tokenize=null;break}n="\\"==e.next()&&!n}return"string"}function F(e){return function(t,n){for(var r;r=t.next();){if("*"==r&&t.eat("/")){if(1==e){n.tokenize=null;break}return n.tokenize=F(e-1),n.tokenize(t,n)}if("/"==r&&t.eat("*"))return n.tokenize=F(e+1),n.tokenize(t,n)}return"comment"}}const P=s({name:"scala",keywords:c("abstract case catch class def do else extends final finally for forSome if implicit import lazy match new null object override package private protected return sealed super this throw trait try type val var while with yield _ assert assume require print println printf readLine readBoolean readByte readShort readChar readInt readLong readFloat readDouble"),types:c("AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either Enumeration Equiv Error Exception Fractional Function IndexedSeq Int Integral Iterable Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable Compiler Double Exception Float Integer Long Math Number Object Package Pair Process Runtime Runnable SecurityManager Short StackTraceElement StrictMath String StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"),multiLineStrings:!0,blockKeywords:c("catch class enum do else finally for forSome if match switch try while"),defKeywords:c("class enum def object package trait type val var"),atoms:c("true false null"),indentStatements:!1,indentSwitch:!1,isOperatorChar:/[+\-*&%=<>!?|\/#:@]/,hooks:{"@":function(e){return e.eatWhile(/[\w\$_]/),"meta"},'"':function(e,t){return!!e.match('""')&&(t.tokenize=E,t.tokenize(e,t))},"'":function(e){return e.match(/^(\\[^'\s]+|[^\\'])'/)?"character":(e.eatWhile(/[\w\$_\xa1-\uffff]/),"atom")},"=":function(e,t){var n=t.context;return!("}"!=n.type||!n.align||!e.eat(">"))&&(t.context=new r(n.indented,n.column,n.type,n.info,null,n.prev),"operator")},"/":function(e,t){return!!e.eat("*")&&(t.tokenize=F(1),t.tokenize(e,t))}},languageData:{closeBrackets:{brackets:["(","[","{","'",'"','"""']}}}),R=s({name:"kotlin",keywords:c("package as typealias class interface this super val operator var fun for is in This throw return annotation break continue object if else while do try when !in !is as? file import where by get set abstract enum open inner override private public internal protected catch finally out final vararg reified dynamic companion constructor init sealed field property receiver param sparam lateinit data inline noinline tailrec external annotation crossinline const operator infix suspend actual expect setparam"),types:c("Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable Compiler Double Exception Float Integer Long Math Number Object Package Pair Process Runtime Runnable SecurityManager Short StackTraceElement StrictMath String StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void Annotation Any BooleanArray ByteArray Char CharArray DeprecationLevel DoubleArray Enum FloatArray Function Int IntArray Lazy LazyThreadSafetyMode LongArray Nothing ShortArray Unit"),intendSwitch:!1,indentStatements:!1,multiLineStrings:!0,number:/^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+(\.\d+)?|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,blockKeywords:c("catch class do else finally for if where try while enum"),defKeywords:c("class val var object interface fun"),atoms:c("true false null this"),hooks:{"@":function(e){return e.eatWhile(/[\w\$_]/),"meta"},"*":function(e,t){return"."==t.prevToken?"variable":"operator"},'"':function(e,t){var n;return t.tokenize=(n=e.match('""'),function(e,t){for(var r,a=!1,o=!1;!e.eol();){if(!n&&!a&&e.match('"')){o=!0;break}if(n&&e.match('"""')){o=!0;break}r=e.next(),!a&&"$"==r&&e.match("{")&&e.skipTo("}"),a=!a&&"\\"==r&&!n}return!o&&n||(t.tokenize=null),"string"}),t.tokenize(e,t)},"/":function(e,t){return!!e.eat("*")&&(t.tokenize=F(1),t.tokenize(e,t))},indent:function(e,t,n,r){var a=n&&n.charAt(0);return"}"!=e.prevToken&&")"!=e.prevToken||""!=n?"operator"==e.prevToken&&"}"!=n&&"}"!=e.context.type||"variable"==e.prevToken&&"."==a||("}"==e.prevToken||")"==e.prevToken)&&"."==a?2*r+t.indented:t.align&&"}"==t.type?t.indented+(e.context.type==(n||"").charAt(0)?0:r):void 0:e.indented}},languageData:{closeBrackets:{brackets:["(","[","{","'",'"','"""']}}}),O=s({name:"shader",keywords:c("sampler1D sampler2D sampler3D samplerCube sampler1DShadow sampler2DShadow const attribute uniform varying break continue discard return for while do if else struct in out inout"),types:c("float int bool void vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 mat2 mat3 mat4"),blockKeywords:c("for while do if else struct"),builtin:c("radians degrees sin cos tan asin acos atan pow exp log exp2 sqrt inversesqrt abs sign floor ceil fract mod min max clamp mix step smoothstep length distance dot cross normalize ftransform faceforward reflect refract matrixCompMult lessThan lessThanEqual greaterThan greaterThanEqual equal notEqual any all not texture1D texture1DProj texture1DLod texture1DProjLod texture2D texture2DProj texture2DLod texture2DProjLod texture3D texture3DProj texture3DLod texture3DProjLod textureCube textureCubeLod shadow1D shadow2D shadow1DProj shadow2DProj shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod dFdx dFdy fwidth noise1 noise2 noise3 noise4"),atoms:c("true false gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_FogCoord gl_PointCoord gl_Position gl_PointSize gl_ClipVertex gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor gl_TexCoord gl_FogFragCoord gl_FragCoord gl_FrontFacing gl_FragData gl_FragDepth gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse gl_TextureMatrixTranspose gl_ModelViewMatrixInverseTranspose gl_ProjectionMatrixInverseTranspose gl_ModelViewProjectionMatrixInverseTranspose gl_TextureMatrixInverseTranspose gl_NormalScale gl_DepthRange gl_ClipPlane gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel gl_FrontLightModelProduct gl_BackLightModelProduct gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ gl_FogParameters gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits gl_MaxDrawBuffers"),indentSwitch:!1,hooks:{"#":w}}),j=s({name:"nesc",keywords:c(d+" as atomic async call command component components configuration event generic implementation includes interface module new norace nx_struct nx_union post provides signal task uses abstract extends"),types:g,blockKeywords:c(b),atoms:c("null true false"),hooks:{"#":w}}),A=s({name:"objectivec",keywords:c(d+" "+p),types:k,builtin:c(m),blockKeywords:c(b+" @synthesize @try @catch @finally @autoreleasepool @synchronized"),defKeywords:c(v+" @interface @implementation @protocol @class"),dontIndentStatements:/^@.*$/,typeFirstDefinitions:!0,atoms:c("YES NO NULL Nil nil true false nullptr"),isReservedIdentifier:x,hooks:{"#":w,"*":_}}),U=s({name:"objectivecpp",keywords:c(d+" "+p+" "+f),types:k,builtin:c(m),blockKeywords:c(b+" @synthesize @try @catch @finally @autoreleasepool @synchronized class try catch"),defKeywords:c(v+" @interface @implementation @protocol @class class namespace"),dontIndentStatements:/^@.*$|^template$/,typeFirstDefinitions:!0,atoms:c("YES NO NULL Nil nil true false nullptr"),isReservedIdentifier:x,hooks:{"#":w,"*":_,u:T,U:T,L:T,R:T,0:S,1:S,2:S,3:S,4:S,5:S,6:S,7:S,8:S,9:S,token:function(e,t,n){if("variable"==n&&"("==e.peek()&&(";"==t.prevToken||null==t.prevToken||"}"==t.prevToken)&&N(e.current()))return"def"}},namespaceSeparator:"::"}),$=s({name:"squirrel",keywords:c("base break clone continue const default delete enum extends function in class foreach local resume return this throw typeof yield constructor instanceof static"),types:g,blockKeywords:c("case catch class else for foreach if switch try while"),defKeywords:c("function local class"),typeFirstDefinitions:!0,atoms:c("true false null"),hooks:{"#":w}});var B=null;function K(e){return function(t,n){for(var r,a=!1,o=!1;!t.eol();){if(!a&&t.match('"')&&("single"==e||t.match('""'))){o=!0;break}if(!a&&t.match("``")){B=K(e),o=!0;break}r=t.next(),a="single"==e&&!a&&"\\"==r}return o&&(n.tokenize=null),"string"}}const q=s({name:"ceylon",keywords:c("abstracts alias assembly assert assign break case catch class continue dynamic else exists extends finally for function given if import in interface is let module new nonempty object of out outer package return satisfies super switch then this throw try value void while"),types:function(e){var t=e.charAt(0);return t===t.toUpperCase()&&t!==t.toLowerCase()},blockKeywords:c("case catch class dynamic else finally for function if interface module new object switch try while"),defKeywords:c("class dynamic function interface module object package value"),builtin:c("abstract actual aliased annotation by default deprecated doc final formal late license native optional sealed see serializable shared suppressWarnings tagged throws variable"),isPunctuationChar:/[\[\]{}\(\),;\:\.`]/,isOperatorChar:/[+\-*&%=<>!?|^~:\/]/,numberStart:/[\d#$]/,number:/^(?:#[\da-fA-F_]+|\$[01_]+|[\d_]+[kMGTPmunpf]?|[\d_]+\.[\d_]+(?:[eE][-+]?\d+|[kMGTPmunpf]|)|)/i,multiLineStrings:!0,typeFirstDefinitions:!0,atoms:c("true false null larger smaller equal empty finished"),indentSwitch:!1,styleDefs:!1,hooks:{"@":function(e){return e.eatWhile(/[\w\$_]/),"meta"},'"':function(e,t){return t.tokenize=K(e.match('""')?"triple":"single"),t.tokenize(e,t)},"`":function(e,t){return!(!B||!e.match("`"))&&(t.tokenize=B,B=null,t.tokenize(e,t))},"'":function(e){return e.match(/^(\\[^'\s]+|[^\\'])'/)?"string.special":(e.eatWhile(/[\w\$_\xa1-\uffff]/),"atom")},token:function(e,t,n){if(("variable"==n||"type"==n)&&"."==t.prevToken)return"variableName.special"}},languageData:{closeBrackets:{brackets:["(","[","{","'",'"','"""']}}});function V(e){(e.interpolationStack||(e.interpolationStack=[])).push(e.tokenize)}function W(e){return(e.interpolationStack||(e.interpolationStack=[])).pop()}function G(e,t,n,r){var a=!1;if(t.eat(e)){if(!t.eat(e))return"string";a=!0}function o(t,n){for(var o=!1;!t.eol();){if(!r&&!o&&"$"==t.peek())return V(n),n.tokenize=Z,"string";var i=t.next();if(i==e&&!o&&(!a||t.match(e+e))){n.tokenize=null;break}o=!r&&!o&&"\\"==i}return"string"}return n.tokenize=o,o(t,n)}function Z(e,t){return e.eat("$"),e.eat("{")?t.tokenize=null:t.tokenize=Q,null}function Q(e,t){return e.eatWhile(/[\w_]/),t.tokenize=W(t),"variable"}const X=s({name:"dart",keywords:c("this super static final const abstract class extends external factory implements mixin get native set typedef with enum throw rethrow assert break case continue default in return new deferred async await covariant try catch finally do else for if switch while import library export part of show hide is as extension on yield late required sealed base interface when inline"),blockKeywords:c("try catch finally do else for if switch while"),builtin:c("void bool num int double dynamic var String Null Never"),atoms:c("true false null"),hooks:{"@":function(e){return e.eatWhile(/[\w\$_\.]/),"meta"},"'":function(e,t){return G("'",e,t,!1)},'"':function(e,t){return G('"',e,t,!1)},r:function(e,t){var n=e.peek();return("'"==n||'"'==n)&&G(e.next(),e,t,!0)},"}":function(e,t){return function(e){return e.interpolationStack?e.interpolationStack.length:0}(t)>0&&(t.tokenize=W(t),null)},"/":function(e,t){return!!e.eat("*")&&(t.tokenize=F(1),t.tokenize(e,t))},token:function(e,t,n){if("variable"==n&&RegExp("^[_$]*[A-Z][a-zA-Z0-9_$]*$","g").test(e.current()))return"type"}}})}}]);
+//# sourceMappingURL=5571.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/5571.index.js.map b/book/_build/html/_static/5571.index.js.map
new file mode 100644
index 0000000..1be2ecf
--- /dev/null
+++ b/book/_build/html/_static/5571.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"5571.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/clike.js"],"sourcesContent":["function Context(indented, column, type, info, align, prev) {\n this.indented = indented;\n this.column = column;\n this.type = type;\n this.info = info;\n this.align = align;\n this.prev = prev;\n}\nfunction pushContext(state, col, type, info) {\n var indent = state.indented;\n if (state.context && state.context.type == \"statement\" && type != \"statement\")\n indent = state.context.indented;\n return state.context = new Context(indent, col, type, info, null, state.context);\n}\nfunction popContext(state) {\n var t = state.context.type;\n if (t == \")\" || t == \"]\" || t == \"}\")\n state.indented = state.context.indented;\n return state.context = state.context.prev;\n}\n\nfunction typeBefore(stream, state, pos) {\n if (state.prevToken == \"variable\" || state.prevToken == \"type\") return true;\n if (/\\S(?:[^- ]>|[*\\]])\\s*$|\\*$/.test(stream.string.slice(0, pos))) return true;\n if (state.typeAtEndOfLine && stream.column() == stream.indentation()) return true;\n}\n\nfunction isTopScope(context) {\n for (;;) {\n if (!context || context.type == \"top\") return true;\n if (context.type == \"}\" && context.prev.info != \"namespace\") return false;\n context = context.prev;\n }\n}\n\nexport function clike(parserConfig) {\n var statementIndentUnit = parserConfig.statementIndentUnit,\n dontAlignCalls = parserConfig.dontAlignCalls,\n keywords = parserConfig.keywords || {},\n types = parserConfig.types || {},\n builtin = parserConfig.builtin || {},\n blockKeywords = parserConfig.blockKeywords || {},\n defKeywords = parserConfig.defKeywords || {},\n atoms = parserConfig.atoms || {},\n hooks = parserConfig.hooks || {},\n multiLineStrings = parserConfig.multiLineStrings,\n indentStatements = parserConfig.indentStatements !== false,\n indentSwitch = parserConfig.indentSwitch !== false,\n namespaceSeparator = parserConfig.namespaceSeparator,\n isPunctuationChar = parserConfig.isPunctuationChar || /[\\[\\]{}\\(\\),;\\:\\.]/,\n numberStart = parserConfig.numberStart || /[\\d\\.]/,\n number = parserConfig.number || /^(?:0x[a-f\\d]+|0b[01]+|(?:\\d+\\.?\\d*|\\.\\d+)(?:e[-+]?\\d+)?)(u|ll?|l|f)?/i,\n isOperatorChar = parserConfig.isOperatorChar || /[+\\-*&%=<>!?|\\/]/,\n isIdentifierChar = parserConfig.isIdentifierChar || /[\\w\\$_\\xa1-\\uffff]/,\n // An optional function that takes a {string} token and returns true if it\n // should be treated as a builtin.\n isReservedIdentifier = parserConfig.isReservedIdentifier || false;\n\n var curPunc, isDefKeyword;\n\n function tokenBase(stream, state) {\n var ch = stream.next();\n if (hooks[ch]) {\n var result = hooks[ch](stream, state);\n if (result !== false) return result;\n }\n if (ch == '\"' || ch == \"'\") {\n state.tokenize = tokenString(ch);\n return state.tokenize(stream, state);\n }\n if (numberStart.test(ch)) {\n stream.backUp(1)\n if (stream.match(number)) return \"number\"\n stream.next()\n }\n if (isPunctuationChar.test(ch)) {\n curPunc = ch;\n return null;\n }\n if (ch == \"/\") {\n if (stream.eat(\"*\")) {\n state.tokenize = tokenComment;\n return tokenComment(stream, state);\n }\n if (stream.eat(\"/\")) {\n stream.skipToEnd();\n return \"comment\";\n }\n }\n if (isOperatorChar.test(ch)) {\n while (!stream.match(/^\\/[\\/*]/, false) && stream.eat(isOperatorChar)) {}\n return \"operator\";\n }\n stream.eatWhile(isIdentifierChar);\n if (namespaceSeparator) while (stream.match(namespaceSeparator))\n stream.eatWhile(isIdentifierChar);\n\n var cur = stream.current();\n if (contains(keywords, cur)) {\n if (contains(blockKeywords, cur)) curPunc = \"newstatement\";\n if (contains(defKeywords, cur)) isDefKeyword = true;\n return \"keyword\";\n }\n if (contains(types, cur)) return \"type\";\n if (contains(builtin, cur)\n || (isReservedIdentifier && isReservedIdentifier(cur))) {\n if (contains(blockKeywords, cur)) curPunc = \"newstatement\";\n return \"builtin\";\n }\n if (contains(atoms, cur)) return \"atom\";\n return \"variable\";\n }\n\n function tokenString(quote) {\n return function(stream, state) {\n var escaped = false, next, end = false;\n while ((next = stream.next()) != null) {\n if (next == quote && !escaped) {end = true; break;}\n escaped = !escaped && next == \"\\\\\";\n }\n if (end || !(escaped || multiLineStrings))\n state.tokenize = null;\n return \"string\";\n };\n }\n\n function tokenComment(stream, state) {\n var maybeEnd = false, ch;\n while (ch = stream.next()) {\n if (ch == \"/\" && maybeEnd) {\n state.tokenize = null;\n break;\n }\n maybeEnd = (ch == \"*\");\n }\n return \"comment\";\n }\n\n function maybeEOL(stream, state) {\n if (parserConfig.typeFirstDefinitions && stream.eol() && isTopScope(state.context))\n state.typeAtEndOfLine = typeBefore(stream, state, stream.pos)\n }\n\n // Interface\n\n return {\n name: parserConfig.name,\n startState: function(indentUnit) {\n return {\n tokenize: null,\n context: new Context(-indentUnit, 0, \"top\", null, false),\n indented: 0,\n startOfLine: true,\n prevToken: null\n };\n },\n\n token: function(stream, state) {\n var ctx = state.context;\n if (stream.sol()) {\n if (ctx.align == null) ctx.align = false;\n state.indented = stream.indentation();\n state.startOfLine = true;\n }\n if (stream.eatSpace()) { maybeEOL(stream, state); return null; }\n curPunc = isDefKeyword = null;\n var style = (state.tokenize || tokenBase)(stream, state);\n if (style == \"comment\" || style == \"meta\") return style;\n if (ctx.align == null) ctx.align = true;\n\n if (curPunc == \";\" || curPunc == \":\" || (curPunc == \",\" && stream.match(/^\\s*(?:\\/\\/.*)?$/, false)))\n while (state.context.type == \"statement\") popContext(state);\n else if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n else if (curPunc == \"}\") {\n while (ctx.type == \"statement\") ctx = popContext(state);\n if (ctx.type == \"}\") ctx = popContext(state);\n while (ctx.type == \"statement\") ctx = popContext(state);\n }\n else if (curPunc == ctx.type) popContext(state);\n else if (indentStatements &&\n (((ctx.type == \"}\" || ctx.type == \"top\") && curPunc != \";\") ||\n (ctx.type == \"statement\" && curPunc == \"newstatement\"))) {\n pushContext(state, stream.column(), \"statement\", stream.current());\n }\n\n if (style == \"variable\" &&\n ((state.prevToken == \"def\" ||\n (parserConfig.typeFirstDefinitions && typeBefore(stream, state, stream.start) &&\n isTopScope(state.context) && stream.match(/^\\s*\\(/, false)))))\n style = \"def\";\n\n if (hooks.token) {\n var result = hooks.token(stream, state, style);\n if (result !== undefined) style = result;\n }\n\n if (style == \"def\" && parserConfig.styleDefs === false) style = \"variable\";\n\n state.startOfLine = false;\n state.prevToken = isDefKeyword ? \"def\" : style || curPunc;\n maybeEOL(stream, state);\n return style;\n },\n\n indent: function(state, textAfter, context) {\n if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine && isTopScope(state.context))\n return null;\n var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);\n var closing = firstChar == ctx.type;\n if (ctx.type == \"statement\" && firstChar == \"}\") ctx = ctx.prev;\n if (parserConfig.dontIndentStatements)\n while (ctx.type == \"statement\" && parserConfig.dontIndentStatements.test(ctx.info))\n ctx = ctx.prev\n if (hooks.indent) {\n var hook = hooks.indent(state, ctx, textAfter, context.unit);\n if (typeof hook == \"number\") return hook\n }\n var switchBlock = ctx.prev && ctx.prev.info == \"switch\";\n if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) {\n while (ctx.type != \"top\" && ctx.type != \"}\") ctx = ctx.prev\n return ctx.indented\n }\n if (ctx.type == \"statement\")\n return ctx.indented + (firstChar == \"{\" ? 0 : statementIndentUnit || context.unit);\n if (ctx.align && (!dontAlignCalls || ctx.type != \")\"))\n return ctx.column + (closing ? 0 : 1);\n if (ctx.type == \")\" && !closing)\n return ctx.indented + (statementIndentUnit || context.unit);\n\n return ctx.indented + (closing ? 0 : context.unit) +\n (!closing && switchBlock && !/^(?:case|default)\\b/.test(textAfter) ? context.unit : 0);\n },\n\n languageData: {\n indentOnInput: indentSwitch ? /^\\s*(?:case .*?:|default:|\\{\\}?|\\})$/ : /^\\s*[{}]$/,\n commentTokens: {line: \"//\", block: {open: \"/*\", close: \"*/\"}},\n autocomplete: Object.keys(keywords).concat(Object.keys(types)).concat(Object.keys(builtin)).concat(Object.keys(atoms)),\n ...parserConfig.languageData\n }\n };\n};\n\nfunction words(str) {\n var obj = {}, words = str.split(\" \");\n for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n return obj;\n}\nfunction contains(words, word) {\n if (typeof words === \"function\") {\n return words(word);\n } else {\n return words.propertyIsEnumerable(word);\n }\n}\nvar cKeywords = \"auto if break case register continue return default do sizeof \" +\n \"static else struct switch extern typedef union for goto while enum const \" +\n \"volatile inline restrict asm fortran\";\n\n// Keywords from https://en.cppreference.com/w/cpp/keyword includes C++20.\nvar cppKeywords = \"alignas alignof and and_eq audit axiom bitand bitor catch \" +\n \"class compl concept constexpr const_cast decltype delete dynamic_cast \" +\n \"explicit export final friend import module mutable namespace new noexcept \" +\n \"not not_eq operator or or_eq override private protected public \" +\n \"reinterpret_cast requires static_assert static_cast template this \" +\n \"thread_local throw try typeid typename using virtual xor xor_eq\";\n\nvar objCKeywords = \"bycopy byref in inout oneway out self super atomic nonatomic retain copy \" +\n \"readwrite readonly strong weak assign typeof nullable nonnull null_resettable _cmd \" +\n \"@interface @implementation @end @protocol @encode @property @synthesize @dynamic @class \" +\n \"@public @package @private @protected @required @optional @try @catch @finally @import \" +\n \"@selector @encode @defs @synchronized @autoreleasepool @compatibility_alias @available\";\n\nvar objCBuiltins = \"FOUNDATION_EXPORT FOUNDATION_EXTERN NS_INLINE NS_FORMAT_FUNCTION \" +\n \" NS_RETURNS_RETAINEDNS_ERROR_ENUM NS_RETURNS_NOT_RETAINED NS_RETURNS_INNER_POINTER \" +\n \"NS_DESIGNATED_INITIALIZER NS_ENUM NS_OPTIONS NS_REQUIRES_NIL_TERMINATION \" +\n \"NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_SWIFT_NAME NS_REFINED_FOR_SWIFT\"\n\n// Do not use this. Use the cTypes function below. This is global just to avoid\n// excessive calls when cTypes is being called multiple times during a parse.\nvar basicCTypes = words(\"int long char short double float unsigned signed \" +\n \"void bool\");\n\n// Do not use this. Use the objCTypes function below. This is global just to avoid\n// excessive calls when objCTypes is being called multiple times during a parse.\nvar basicObjCTypes = words(\"SEL instancetype id Class Protocol BOOL\");\n\n// Returns true if identifier is a \"C\" type.\n// C type is defined as those that are reserved by the compiler (basicTypes),\n// and those that end in _t (Reserved by POSIX for types)\n// http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html\nfunction cTypes(identifier) {\n return contains(basicCTypes, identifier) || /.+_t$/.test(identifier);\n}\n\n// Returns true if identifier is a \"Objective C\" type.\nfunction objCTypes(identifier) {\n return cTypes(identifier) || contains(basicObjCTypes, identifier);\n}\n\nvar cBlockKeywords = \"case do else for if switch while struct enum union\";\nvar cDefKeywords = \"struct enum union\";\n\nfunction cppHook(stream, state) {\n if (!state.startOfLine) return false\n for (var ch, next = null; ch = stream.peek();) {\n if (ch == \"\\\\\" && stream.match(/^.$/)) {\n next = cppHook\n break\n } else if (ch == \"/\" && stream.match(/^\\/[\\/\\*]/, false)) {\n break\n }\n stream.next()\n }\n state.tokenize = next\n return \"meta\"\n}\n\nfunction pointerHook(_stream, state) {\n if (state.prevToken == \"type\") return \"type\";\n return false;\n}\n\n// For C and C++ (and ObjC): identifiers starting with __\n// or _ followed by a capital letter are reserved for the compiler.\nfunction cIsReservedIdentifier(token) {\n if (!token || token.length < 2) return false;\n if (token[0] != '_') return false;\n return (token[1] == '_') || (token[1] !== token[1].toLowerCase());\n}\n\nfunction cpp14Literal(stream) {\n stream.eatWhile(/[\\w\\.']/);\n return \"number\";\n}\n\nfunction cpp11StringHook(stream, state) {\n stream.backUp(1);\n // Raw strings.\n if (stream.match(/^(?:R|u8R|uR|UR|LR)/)) {\n var match = stream.match(/^\"([^\\s\\\\()]{0,16})\\(/);\n if (!match) {\n return false;\n }\n state.cpp11RawStringDelim = match[1];\n state.tokenize = tokenRawString;\n return tokenRawString(stream, state);\n }\n // Unicode strings/chars.\n if (stream.match(/^(?:u8|u|U|L)/)) {\n if (stream.match(/^[\"']/, /* eat */ false)) {\n return \"string\";\n }\n return false;\n }\n // Ignore this hook.\n stream.next();\n return false;\n}\n\nfunction cppLooksLikeConstructor(word) {\n var lastTwo = /(\\w+)::~?(\\w+)$/.exec(word);\n return lastTwo && lastTwo[1] == lastTwo[2];\n}\n\n// C#-style strings where \"\" escapes a quote.\nfunction tokenAtString(stream, state) {\n var next;\n while ((next = stream.next()) != null) {\n if (next == '\"' && !stream.eat('\"')) {\n state.tokenize = null;\n break;\n }\n }\n return \"string\";\n}\n\n// C++11 raw string literal is \"( anything )\", where\n// can be a string up to 16 characters long.\nfunction tokenRawString(stream, state) {\n // Escape characters that have special regex meanings.\n var delim = state.cpp11RawStringDelim.replace(/[^\\w\\s]/g, '\\\\$&');\n var match = stream.match(new RegExp(\".*?\\\\)\" + delim + '\"'));\n if (match)\n state.tokenize = null;\n else\n stream.skipToEnd();\n return \"string\";\n}\n\nexport const c = clike({\n name: \"c\",\n keywords: words(cKeywords),\n types: cTypes,\n blockKeywords: words(cBlockKeywords),\n defKeywords: words(cDefKeywords),\n typeFirstDefinitions: true,\n atoms: words(\"NULL true false\"),\n isReservedIdentifier: cIsReservedIdentifier,\n hooks: {\n \"#\": cppHook,\n \"*\": pointerHook,\n }\n})\n\nexport const cpp = clike({\n name: \"cpp\",\n keywords: words(cKeywords + \" \" + cppKeywords),\n types: cTypes,\n blockKeywords: words(cBlockKeywords + \" class try catch\"),\n defKeywords: words(cDefKeywords + \" class namespace\"),\n typeFirstDefinitions: true,\n atoms: words(\"true false NULL nullptr\"),\n dontIndentStatements: /^template$/,\n isIdentifierChar: /[\\w\\$_~\\xa1-\\uffff]/,\n isReservedIdentifier: cIsReservedIdentifier,\n hooks: {\n \"#\": cppHook,\n \"*\": pointerHook,\n \"u\": cpp11StringHook,\n \"U\": cpp11StringHook,\n \"L\": cpp11StringHook,\n \"R\": cpp11StringHook,\n \"0\": cpp14Literal,\n \"1\": cpp14Literal,\n \"2\": cpp14Literal,\n \"3\": cpp14Literal,\n \"4\": cpp14Literal,\n \"5\": cpp14Literal,\n \"6\": cpp14Literal,\n \"7\": cpp14Literal,\n \"8\": cpp14Literal,\n \"9\": cpp14Literal,\n token: function(stream, state, style) {\n if (style == \"variable\" && stream.peek() == \"(\" &&\n (state.prevToken == \";\" || state.prevToken == null ||\n state.prevToken == \"}\") &&\n cppLooksLikeConstructor(stream.current()))\n return \"def\";\n }\n },\n namespaceSeparator: \"::\"\n});\n\nexport const java = clike({\n name: \"java\",\n keywords: words(\"abstract assert break case catch class const continue default \" +\n \"do else enum extends final finally for goto if implements import \" +\n \"instanceof interface native new package private protected public \" +\n \"return static strictfp super switch synchronized this throw throws transient \" +\n \"try volatile while @interface\"),\n types: words(\"var byte short int long float double boolean char void Boolean Byte Character Double Float \" +\n \"Integer Long Number Object Short String StringBuffer StringBuilder Void\"),\n blockKeywords: words(\"catch class do else finally for if switch try while\"),\n defKeywords: words(\"class interface enum @interface\"),\n typeFirstDefinitions: true,\n atoms: words(\"true false null\"),\n number: /^(?:0x[a-f\\d_]+|0b[01_]+|(?:[\\d_]+\\.?\\d*|\\.\\d+)(?:e[-+]?[\\d_]+)?)(u|ll?|l|f)?/i,\n hooks: {\n \"@\": function(stream) {\n // Don't match the @interface keyword.\n if (stream.match('interface', false)) return false;\n\n stream.eatWhile(/[\\w\\$_]/);\n return \"meta\";\n },\n '\"': function(stream, state) {\n if (!stream.match(/\"\"$/)) return false;\n state.tokenize = tokenTripleString;\n return state.tokenize(stream, state);\n }\n }\n})\n\nexport const csharp = clike({\n name: \"csharp\",\n keywords: words(\"abstract as async await base break case catch checked class const continue\" +\n \" default delegate do else enum event explicit extern finally fixed for\" +\n \" foreach goto if implicit in init interface internal is lock namespace new\" +\n \" operator out override params private protected public readonly record ref required return sealed\" +\n \" sizeof stackalloc static struct switch this throw try typeof unchecked\" +\n \" unsafe using virtual void volatile while add alias ascending descending dynamic from get\" +\n \" global group into join let orderby partial remove select set value var yield\"),\n types: words(\"Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func\" +\n \" Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32\" +\n \" UInt64 bool byte char decimal double short int long object\" +\n \" sbyte float string ushort uint ulong\"),\n blockKeywords: words(\"catch class do else finally for foreach if struct switch try while\"),\n defKeywords: words(\"class interface namespace record struct var\"),\n typeFirstDefinitions: true,\n atoms: words(\"true false null\"),\n hooks: {\n \"@\": function(stream, state) {\n if (stream.eat('\"')) {\n state.tokenize = tokenAtString;\n return tokenAtString(stream, state);\n }\n stream.eatWhile(/[\\w\\$_]/);\n return \"meta\";\n }\n }\n});\n\nfunction tokenTripleString(stream, state) {\n var escaped = false;\n while (!stream.eol()) {\n if (!escaped && stream.match('\"\"\"')) {\n state.tokenize = null;\n break;\n }\n escaped = stream.next() == \"\\\\\" && !escaped;\n }\n return \"string\";\n}\n\nfunction tokenNestedComment(depth) {\n return function (stream, state) {\n var ch\n while (ch = stream.next()) {\n if (ch == \"*\" && stream.eat(\"/\")) {\n if (depth == 1) {\n state.tokenize = null\n break\n } else {\n state.tokenize = tokenNestedComment(depth - 1)\n return state.tokenize(stream, state)\n }\n } else if (ch == \"/\" && stream.eat(\"*\")) {\n state.tokenize = tokenNestedComment(depth + 1)\n return state.tokenize(stream, state)\n }\n }\n return \"comment\"\n }\n}\n\nexport const scala = clike({\n name: \"scala\",\n keywords: words(\n /* scala */\n \"abstract case catch class def do else extends final finally for forSome if \" +\n \"implicit import lazy match new null object override package private protected return \" +\n \"sealed super this throw trait try type val var while with yield _ \" +\n\n /* package scala */\n \"assert assume require print println printf readLine readBoolean readByte readShort \" +\n \"readChar readInt readLong readFloat readDouble\"\n ),\n types: words(\n \"AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either \" +\n \"Enumeration Equiv Error Exception Fractional Function IndexedSeq Int Integral Iterable \" +\n \"Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering \" +\n \"Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder \" +\n \"StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector \" +\n\n /* package java.lang */\n \"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable \" +\n \"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process \" +\n \"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String \" +\n \"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void\"\n ),\n multiLineStrings: true,\n blockKeywords: words(\"catch class enum do else finally for forSome if match switch try while\"),\n defKeywords: words(\"class enum def object package trait type val var\"),\n atoms: words(\"true false null\"),\n indentStatements: false,\n indentSwitch: false,\n isOperatorChar: /[+\\-*&%=<>!?|\\/#:@]/,\n hooks: {\n \"@\": function(stream) {\n stream.eatWhile(/[\\w\\$_]/);\n return \"meta\";\n },\n '\"': function(stream, state) {\n if (!stream.match('\"\"')) return false;\n state.tokenize = tokenTripleString;\n return state.tokenize(stream, state);\n },\n \"'\": function(stream) {\n if (stream.match(/^(\\\\[^'\\s]+|[^\\\\'])'/)) return \"character\"\n stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n return \"atom\";\n },\n \"=\": function(stream, state) {\n var cx = state.context\n if (cx.type == \"}\" && cx.align && stream.eat(\">\")) {\n state.context = new Context(cx.indented, cx.column, cx.type, cx.info, null, cx.prev)\n return \"operator\"\n } else {\n return false\n }\n },\n\n \"/\": function(stream, state) {\n if (!stream.eat(\"*\")) return false\n state.tokenize = tokenNestedComment(1)\n return state.tokenize(stream, state)\n }\n },\n languageData: {\n closeBrackets: {brackets: [\"(\", \"[\", \"{\", \"'\", '\"', '\"\"\"']}\n }\n});\n\nfunction tokenKotlinString(tripleString){\n return function (stream, state) {\n var escaped = false, next, end = false;\n while (!stream.eol()) {\n if (!tripleString && !escaped && stream.match('\"') ) {end = true; break;}\n if (tripleString && stream.match('\"\"\"')) {end = true; break;}\n next = stream.next();\n if(!escaped && next == \"$\" && stream.match('{'))\n stream.skipTo(\"}\");\n escaped = !escaped && next == \"\\\\\" && !tripleString;\n }\n if (end || !tripleString)\n state.tokenize = null;\n return \"string\";\n }\n}\n\nexport const kotlin = clike({\n name: \"kotlin\",\n keywords: words(\n /*keywords*/\n \"package as typealias class interface this super val operator \" +\n \"var fun for is in This throw return annotation \" +\n \"break continue object if else while do try when !in !is as? \" +\n\n /*soft keywords*/\n \"file import where by get set abstract enum open inner override private public internal \" +\n \"protected catch finally out final vararg reified dynamic companion constructor init \" +\n \"sealed field property receiver param sparam lateinit data inline noinline tailrec \" +\n \"external annotation crossinline const operator infix suspend actual expect setparam\"\n ),\n types: words(\n /* package java.lang */\n \"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable \" +\n \"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process \" +\n \"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String \" +\n \"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void Annotation Any BooleanArray \" +\n \"ByteArray Char CharArray DeprecationLevel DoubleArray Enum FloatArray Function Int IntArray Lazy \" +\n \"LazyThreadSafetyMode LongArray Nothing ShortArray Unit\"\n ),\n intendSwitch: false,\n indentStatements: false,\n multiLineStrings: true,\n number: /^(?:0x[a-f\\d_]+|0b[01_]+|(?:[\\d_]+(\\.\\d+)?|\\.\\d+)(?:e[-+]?[\\d_]+)?)(u|ll?|l|f)?/i,\n blockKeywords: words(\"catch class do else finally for if where try while enum\"),\n defKeywords: words(\"class val var object interface fun\"),\n atoms: words(\"true false null this\"),\n hooks: {\n \"@\": function(stream) {\n stream.eatWhile(/[\\w\\$_]/);\n return \"meta\";\n },\n '*': function(_stream, state) {\n return state.prevToken == '.' ? 'variable' : 'operator';\n },\n '\"': function(stream, state) {\n state.tokenize = tokenKotlinString(stream.match('\"\"'));\n return state.tokenize(stream, state);\n },\n \"/\": function(stream, state) {\n if (!stream.eat(\"*\")) return false;\n state.tokenize = tokenNestedComment(1);\n return state.tokenize(stream, state)\n },\n indent: function(state, ctx, textAfter, indentUnit) {\n var firstChar = textAfter && textAfter.charAt(0);\n if ((state.prevToken == \"}\" || state.prevToken == \")\") && textAfter == \"\")\n return state.indented;\n if ((state.prevToken == \"operator\" && textAfter != \"}\" && state.context.type != \"}\") ||\n state.prevToken == \"variable\" && firstChar == \".\" ||\n (state.prevToken == \"}\" || state.prevToken == \")\") && firstChar == \".\")\n return indentUnit * 2 + ctx.indented;\n if (ctx.align && ctx.type == \"}\")\n return ctx.indented + (state.context.type == (textAfter || \"\").charAt(0) ? 0 : indentUnit);\n }\n },\n languageData: {\n closeBrackets: {brackets: [\"(\", \"[\", \"{\", \"'\", '\"', '\"\"\"']}\n }\n});\n\nexport const shader = clike({\n name: \"shader\",\n keywords: words(\"sampler1D sampler2D sampler3D samplerCube \" +\n \"sampler1DShadow sampler2DShadow \" +\n \"const attribute uniform varying \" +\n \"break continue discard return \" +\n \"for while do if else struct \" +\n \"in out inout\"),\n types: words(\"float int bool void \" +\n \"vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 \" +\n \"mat2 mat3 mat4\"),\n blockKeywords: words(\"for while do if else struct\"),\n builtin: words(\"radians degrees sin cos tan asin acos atan \" +\n \"pow exp log exp2 sqrt inversesqrt \" +\n \"abs sign floor ceil fract mod min max clamp mix step smoothstep \" +\n \"length distance dot cross normalize ftransform faceforward \" +\n \"reflect refract matrixCompMult \" +\n \"lessThan lessThanEqual greaterThan greaterThanEqual \" +\n \"equal notEqual any all not \" +\n \"texture1D texture1DProj texture1DLod texture1DProjLod \" +\n \"texture2D texture2DProj texture2DLod texture2DProjLod \" +\n \"texture3D texture3DProj texture3DLod texture3DProjLod \" +\n \"textureCube textureCubeLod \" +\n \"shadow1D shadow2D shadow1DProj shadow2DProj \" +\n \"shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod \" +\n \"dFdx dFdy fwidth \" +\n \"noise1 noise2 noise3 noise4\"),\n atoms: words(\"true false \" +\n \"gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex \" +\n \"gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 \" +\n \"gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 \" +\n \"gl_FogCoord gl_PointCoord \" +\n \"gl_Position gl_PointSize gl_ClipVertex \" +\n \"gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor \" +\n \"gl_TexCoord gl_FogFragCoord \" +\n \"gl_FragCoord gl_FrontFacing \" +\n \"gl_FragData gl_FragDepth \" +\n \"gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix \" +\n \"gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse \" +\n \"gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse \" +\n \"gl_TextureMatrixTranspose gl_ModelViewMatrixInverseTranspose \" +\n \"gl_ProjectionMatrixInverseTranspose \" +\n \"gl_ModelViewProjectionMatrixInverseTranspose \" +\n \"gl_TextureMatrixInverseTranspose \" +\n \"gl_NormalScale gl_DepthRange gl_ClipPlane \" +\n \"gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel \" +\n \"gl_FrontLightModelProduct gl_BackLightModelProduct \" +\n \"gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ \" +\n \"gl_FogParameters \" +\n \"gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords \" +\n \"gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats \" +\n \"gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits \" +\n \"gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits \" +\n \"gl_MaxDrawBuffers\"),\n indentSwitch: false,\n hooks: {\"#\": cppHook}\n})\n\nexport const nesC = clike({\n name: \"nesc\",\n keywords: words(cKeywords + \" as atomic async call command component components configuration event generic \" +\n \"implementation includes interface module new norace nx_struct nx_union post provides \" +\n \"signal task uses abstract extends\"),\n types: cTypes,\n blockKeywords: words(cBlockKeywords),\n atoms: words(\"null true false\"),\n hooks: {\"#\": cppHook}\n})\n\nexport const objectiveC = clike({\n name: \"objectivec\",\n keywords: words(cKeywords + \" \" + objCKeywords),\n types: objCTypes,\n builtin: words(objCBuiltins),\n blockKeywords: words(cBlockKeywords + \" @synthesize @try @catch @finally @autoreleasepool @synchronized\"),\n defKeywords: words(cDefKeywords + \" @interface @implementation @protocol @class\"),\n dontIndentStatements: /^@.*$/,\n typeFirstDefinitions: true,\n atoms: words(\"YES NO NULL Nil nil true false nullptr\"),\n isReservedIdentifier: cIsReservedIdentifier,\n hooks: {\n \"#\": cppHook,\n \"*\": pointerHook,\n }\n})\n\nexport const objectiveCpp = clike({\n name: \"objectivecpp\",\n keywords: words(cKeywords + \" \" + objCKeywords + \" \" + cppKeywords),\n types: objCTypes,\n builtin: words(objCBuiltins),\n blockKeywords: words(cBlockKeywords + \" @synthesize @try @catch @finally @autoreleasepool @synchronized class try catch\"),\n defKeywords: words(cDefKeywords + \" @interface @implementation @protocol @class class namespace\"),\n dontIndentStatements: /^@.*$|^template$/,\n typeFirstDefinitions: true,\n atoms: words(\"YES NO NULL Nil nil true false nullptr\"),\n isReservedIdentifier: cIsReservedIdentifier,\n hooks: {\n \"#\": cppHook,\n \"*\": pointerHook,\n \"u\": cpp11StringHook,\n \"U\": cpp11StringHook,\n \"L\": cpp11StringHook,\n \"R\": cpp11StringHook,\n \"0\": cpp14Literal,\n \"1\": cpp14Literal,\n \"2\": cpp14Literal,\n \"3\": cpp14Literal,\n \"4\": cpp14Literal,\n \"5\": cpp14Literal,\n \"6\": cpp14Literal,\n \"7\": cpp14Literal,\n \"8\": cpp14Literal,\n \"9\": cpp14Literal,\n token: function(stream, state, style) {\n if (style == \"variable\" && stream.peek() == \"(\" &&\n (state.prevToken == \";\" || state.prevToken == null ||\n state.prevToken == \"}\") &&\n cppLooksLikeConstructor(stream.current()))\n return \"def\";\n }\n },\n namespaceSeparator: \"::\"\n})\n\nexport const squirrel = clike({\n name: \"squirrel\",\n keywords: words(\"base break clone continue const default delete enum extends function in class\" +\n \" foreach local resume return this throw typeof yield constructor instanceof static\"),\n types: cTypes,\n blockKeywords: words(\"case catch class else for foreach if switch try while\"),\n defKeywords: words(\"function local class\"),\n typeFirstDefinitions: true,\n atoms: words(\"true false null\"),\n hooks: {\"#\": cppHook}\n})\n\n// Ceylon Strings need to deal with interpolation\nvar stringTokenizer = null;\nfunction tokenCeylonString(type) {\n return function(stream, state) {\n var escaped = false, next, end = false;\n while (!stream.eol()) {\n if (!escaped && stream.match('\"') &&\n (type == \"single\" || stream.match('\"\"'))) {\n end = true;\n break;\n }\n if (!escaped && stream.match('``')) {\n stringTokenizer = tokenCeylonString(type);\n end = true;\n break;\n }\n next = stream.next();\n escaped = type == \"single\" && !escaped && next == \"\\\\\";\n }\n if (end)\n state.tokenize = null;\n return \"string\";\n }\n}\n\nexport const ceylon = clike({\n name: \"ceylon\",\n keywords: words(\"abstracts alias assembly assert assign break case catch class continue dynamic else\" +\n \" exists extends finally for function given if import in interface is let module new\" +\n \" nonempty object of out outer package return satisfies super switch then this throw\" +\n \" try value void while\"),\n types: function(word) {\n // In Ceylon all identifiers that start with an uppercase are types\n var first = word.charAt(0);\n return (first === first.toUpperCase() && first !== first.toLowerCase());\n },\n blockKeywords: words(\"case catch class dynamic else finally for function if interface module new object switch try while\"),\n defKeywords: words(\"class dynamic function interface module object package value\"),\n builtin: words(\"abstract actual aliased annotation by default deprecated doc final formal late license\" +\n \" native optional sealed see serializable shared suppressWarnings tagged throws variable\"),\n isPunctuationChar: /[\\[\\]{}\\(\\),;\\:\\.`]/,\n isOperatorChar: /[+\\-*&%=<>!?|^~:\\/]/,\n numberStart: /[\\d#$]/,\n number: /^(?:#[\\da-fA-F_]+|\\$[01_]+|[\\d_]+[kMGTPmunpf]?|[\\d_]+\\.[\\d_]+(?:[eE][-+]?\\d+|[kMGTPmunpf]|)|)/i,\n multiLineStrings: true,\n typeFirstDefinitions: true,\n atoms: words(\"true false null larger smaller equal empty finished\"),\n indentSwitch: false,\n styleDefs: false,\n hooks: {\n \"@\": function(stream) {\n stream.eatWhile(/[\\w\\$_]/);\n return \"meta\";\n },\n '\"': function(stream, state) {\n state.tokenize = tokenCeylonString(stream.match('\"\"') ? \"triple\" : \"single\");\n return state.tokenize(stream, state);\n },\n '`': function(stream, state) {\n if (!stringTokenizer || !stream.match('`')) return false;\n state.tokenize = stringTokenizer;\n stringTokenizer = null;\n return state.tokenize(stream, state);\n },\n \"'\": function(stream) {\n if (stream.match(/^(\\\\[^'\\s]+|[^\\\\'])'/)) return \"string.special\"\n stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n return \"atom\";\n },\n token: function(_stream, state, style) {\n if ((style == \"variable\" || style == \"type\") &&\n state.prevToken == \".\") {\n return \"variableName.special\";\n }\n }\n },\n languageData: {\n closeBrackets: {brackets: [\"(\", \"[\", \"{\", \"'\", '\"', '\"\"\"']}\n }\n})\n\nfunction pushInterpolationStack(state) {\n (state.interpolationStack || (state.interpolationStack = [])).push(state.tokenize);\n}\n\nfunction popInterpolationStack(state) {\n return (state.interpolationStack || (state.interpolationStack = [])).pop();\n}\n\nfunction sizeInterpolationStack(state) {\n return state.interpolationStack ? state.interpolationStack.length : 0;\n}\n\nfunction tokenDartString(quote, stream, state, raw) {\n var tripleQuoted = false;\n if (stream.eat(quote)) {\n if (stream.eat(quote)) tripleQuoted = true;\n else return \"string\"; //empty string\n }\n function tokenStringHelper(stream, state) {\n var escaped = false;\n while (!stream.eol()) {\n if (!raw && !escaped && stream.peek() == \"$\") {\n pushInterpolationStack(state);\n state.tokenize = tokenInterpolation;\n return \"string\";\n }\n var next = stream.next();\n if (next == quote && !escaped && (!tripleQuoted || stream.match(quote + quote))) {\n state.tokenize = null;\n break;\n }\n escaped = !raw && !escaped && next == \"\\\\\";\n }\n return \"string\";\n }\n state.tokenize = tokenStringHelper;\n return tokenStringHelper(stream, state);\n}\n\nfunction tokenInterpolation(stream, state) {\n stream.eat(\"$\");\n if (stream.eat(\"{\")) {\n // let clike handle the content of ${...},\n // we take over again when \"}\" appears (see hooks).\n state.tokenize = null;\n } else {\n state.tokenize = tokenInterpolationIdentifier;\n }\n return null;\n}\n\nfunction tokenInterpolationIdentifier(stream, state) {\n stream.eatWhile(/[\\w_]/);\n state.tokenize = popInterpolationStack(state);\n return \"variable\";\n}\n\nexport const dart = clike({\n name: \"dart\",\n keywords: words(\"this super static final const abstract class extends external factory \" +\n \"implements mixin get native set typedef with enum throw rethrow assert break case \" +\n \"continue default in return new deferred async await covariant try catch finally \" +\n \"do else for if switch while import library export part of show hide is as extension \" +\n \"on yield late required sealed base interface when inline\"),\n blockKeywords: words(\"try catch finally do else for if switch while\"),\n builtin: words(\"void bool num int double dynamic var String Null Never\"),\n atoms: words(\"true false null\"),\n hooks: {\n \"@\": function(stream) {\n stream.eatWhile(/[\\w\\$_\\.]/);\n return \"meta\";\n },\n\n // custom string handling to deal with triple-quoted strings and string interpolation\n \"'\": function(stream, state) {\n return tokenDartString(\"'\", stream, state, false);\n },\n \"\\\"\": function(stream, state) {\n return tokenDartString(\"\\\"\", stream, state, false);\n },\n \"r\": function(stream, state) {\n var peek = stream.peek();\n if (peek == \"'\" || peek == \"\\\"\") {\n return tokenDartString(stream.next(), stream, state, true);\n }\n return false;\n },\n\n \"}\": function(_stream, state) {\n // \"}\" is end of interpolation, if interpolation stack is non-empty\n if (sizeInterpolationStack(state) > 0) {\n state.tokenize = popInterpolationStack(state);\n return null;\n }\n return false;\n },\n\n \"/\": function(stream, state) {\n if (!stream.eat(\"*\")) return false\n state.tokenize = tokenNestedComment(1)\n return state.tokenize(stream, state)\n },\n token: function(stream, _, style) {\n if (style == \"variable\") {\n // Assume uppercase symbols are classes\n var isUpper = RegExp('^[_$]*[A-Z][a-zA-Z0-9_$]*$','g');\n if (isUpper.test(stream.current())) {\n return 'type';\n }\n }\n }\n }\n})\n"],"names":["Context","indented","column","type","info","align","prev","this","pushContext","state","col","indent","context","popContext","t","typeBefore","stream","pos","prevToken","test","string","slice","typeAtEndOfLine","indentation","isTopScope","clike","parserConfig","curPunc","isDefKeyword","statementIndentUnit","dontAlignCalls","keywords","types","builtin","blockKeywords","defKeywords","atoms","hooks","multiLineStrings","indentStatements","indentSwitch","namespaceSeparator","isPunctuationChar","numberStart","number","isOperatorChar","isIdentifierChar","isReservedIdentifier","tokenBase","quote","ch","next","result","tokenize","escaped","end","backUp","match","eat","tokenComment","skipToEnd","eatWhile","cur","current","contains","maybeEnd","maybeEOL","typeFirstDefinitions","eol","name","startState","indentUnit","startOfLine","token","ctx","sol","eatSpace","style","start","undefined","styleDefs","textAfter","firstChar","charAt","closing","dontIndentStatements","hook","unit","switchBlock","allmanIndentation","languageData","indentOnInput","commentTokens","line","block","open","close","autocomplete","Object","keys","concat","words","str","obj","split","i","length","word","propertyIsEnumerable","cKeywords","cppKeywords","objCKeywords","objCBuiltins","basicCTypes","basicObjCTypes","cTypes","identifier","objCTypes","cBlockKeywords","cDefKeywords","cppHook","peek","pointerHook","_stream","cIsReservedIdentifier","toLowerCase","cpp14Literal","cpp11StringHook","cpp11RawStringDelim","tokenRawString","cppLooksLikeConstructor","lastTwo","exec","tokenAtString","delim","replace","RegExp","c","cpp","java","tokenTripleString","csharp","tokenNestedComment","depth","scala","cx","closeBrackets","brackets","kotlin","intendSwitch","tripleString","skipTo","shader","nesC","objectiveC","objectiveCpp","squirrel","stringTokenizer","tokenCeylonString","ceylon","first","toUpperCase","pushInterpolationStack","interpolationStack","push","popInterpolationStack","pop","tokenDartString","raw","tripleQuoted","tokenStringHelper","tokenInterpolation","tokenInterpolationIdentifier","dart","sizeInterpolationStack","_"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/5808.index.js b/book/_build/html/_static/5808.index.js
new file mode 100644
index 0000000..a92a234
--- /dev/null
+++ b/book/_build/html/_static/5808.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[5808],{45808:(e,t,n)=>{n.r(t),n.d(t,{clojure:()=>g});var r=["false","nil","true"],a=[".","catch","def","do","if","monitor-enter","monitor-exit","new","quote","recur","set!","throw","try","var"],s=["*","*'","*1","*2","*3","*agent*","*allow-unresolved-vars*","*assert*","*clojure-version*","*command-line-args*","*compile-files*","*compile-path*","*compiler-options*","*data-readers*","*default-data-reader-fn*","*e","*err*","*file*","*flush-on-newline*","*fn-loader*","*in*","*math-context*","*ns*","*out*","*print-dup*","*print-length*","*print-level*","*print-meta*","*print-namespace-maps*","*print-readably*","*read-eval*","*reader-resolver*","*source-path*","*suppress-read*","*unchecked-math*","*use-context-classloader*","*verbose-defrecords*","*warn-on-reflection*","+","+'","-","-'","->","->>","->ArrayChunk","->Eduction","->Vec","->VecNode","->VecSeq","-cache-protocol-fn","-reset-methods","..","/","<","<=","=","==",">",">=","EMPTY-NODE","Inst","StackTraceElement->vec","Throwable->map","accessor","aclone","add-classpath","add-watch","agent","agent-error","agent-errors","aget","alength","alias","all-ns","alter","alter-meta!","alter-var-root","amap","ancestors","and","any?","apply","areduce","array-map","as->","aset","aset-boolean","aset-byte","aset-char","aset-double","aset-float","aset-int","aset-long","aset-short","assert","assoc","assoc!","assoc-in","associative?","atom","await","await-for","await1","bases","bean","bigdec","bigint","biginteger","binding","bit-and","bit-and-not","bit-clear","bit-flip","bit-not","bit-or","bit-set","bit-shift-left","bit-shift-right","bit-test","bit-xor","boolean","boolean-array","boolean?","booleans","bound-fn","bound-fn*","bound?","bounded-count","butlast","byte","byte-array","bytes","bytes?","case","cast","cat","char","char-array","char-escape-string","char-name-string","char?","chars","chunk","chunk-append","chunk-buffer","chunk-cons","chunk-first","chunk-next","chunk-rest","chunked-seq?","class","class?","clear-agent-errors","clojure-version","coll?","comment","commute","comp","comparator","compare","compare-and-set!","compile","complement","completing","concat","cond","cond->","cond->>","condp","conj","conj!","cons","constantly","construct-proxy","contains?","count","counted?","create-ns","create-struct","cycle","dec","dec'","decimal?","declare","dedupe","default-data-readers","definline","definterface","defmacro","defmethod","defmulti","defn","defn-","defonce","defprotocol","defrecord","defstruct","deftype","delay","delay?","deliver","denominator","deref","derive","descendants","destructure","disj","disj!","dissoc","dissoc!","distinct","distinct?","doall","dorun","doseq","dosync","dotimes","doto","double","double-array","double?","doubles","drop","drop-last","drop-while","eduction","empty","empty?","ensure","ensure-reduced","enumeration-seq","error-handler","error-mode","eval","even?","every-pred","every?","ex-data","ex-info","extend","extend-protocol","extend-type","extenders","extends?","false?","ffirst","file-seq","filter","filterv","find","find-keyword","find-ns","find-protocol-impl","find-protocol-method","find-var","first","flatten","float","float-array","float?","floats","flush","fn","fn?","fnext","fnil","for","force","format","frequencies","future","future-call","future-cancel","future-cancelled?","future-done?","future?","gen-class","gen-interface","gensym","get","get-in","get-method","get-proxy-class","get-thread-bindings","get-validator","group-by","halt-when","hash","hash-combine","hash-map","hash-ordered-coll","hash-set","hash-unordered-coll","ident?","identical?","identity","if-let","if-not","if-some","ifn?","import","in-ns","inc","inc'","indexed?","init-proxy","inst-ms","inst-ms*","inst?","instance?","int","int-array","int?","integer?","interleave","intern","interpose","into","into-array","ints","io!","isa?","iterate","iterator-seq","juxt","keep","keep-indexed","key","keys","keyword","keyword?","last","lazy-cat","lazy-seq","let","letfn","line-seq","list","list*","list?","load","load-file","load-reader","load-string","loaded-libs","locking","long","long-array","longs","loop","macroexpand","macroexpand-1","make-array","make-hierarchy","map","map-entry?","map-indexed","map?","mapcat","mapv","max","max-key","memfn","memoize","merge","merge-with","meta","method-sig","methods","min","min-key","mix-collection-hash","mod","munge","name","namespace","namespace-munge","nat-int?","neg-int?","neg?","newline","next","nfirst","nil?","nnext","not","not-any?","not-empty","not-every?","not=","ns","ns-aliases","ns-imports","ns-interns","ns-map","ns-name","ns-publics","ns-refers","ns-resolve","ns-unalias","ns-unmap","nth","nthnext","nthrest","num","number?","numerator","object-array","odd?","or","parents","partial","partition","partition-all","partition-by","pcalls","peek","persistent!","pmap","pop","pop!","pop-thread-bindings","pos-int?","pos?","pr","pr-str","prefer-method","prefers","primitives-classnames","print","print-ctor","print-dup","print-method","print-simple","print-str","printf","println","println-str","prn","prn-str","promise","proxy","proxy-call-with-super","proxy-mappings","proxy-name","proxy-super","push-thread-bindings","pvalues","qualified-ident?","qualified-keyword?","qualified-symbol?","quot","rand","rand-int","rand-nth","random-sample","range","ratio?","rational?","rationalize","re-find","re-groups","re-matcher","re-matches","re-pattern","re-seq","read","read-line","read-string","reader-conditional","reader-conditional?","realized?","record?","reduce","reduce-kv","reduced","reduced?","reductions","ref","ref-history-count","ref-max-history","ref-min-history","ref-set","refer","refer-clojure","reify","release-pending-sends","rem","remove","remove-all-methods","remove-method","remove-ns","remove-watch","repeat","repeatedly","replace","replicate","require","reset!","reset-meta!","reset-vals!","resolve","rest","restart-agent","resultset-seq","reverse","reversible?","rseq","rsubseq","run!","satisfies?","second","select-keys","send","send-off","send-via","seq","seq?","seqable?","seque","sequence","sequential?","set","set-agent-send-executor!","set-agent-send-off-executor!","set-error-handler!","set-error-mode!","set-validator!","set?","short","short-array","shorts","shuffle","shutdown-agents","simple-ident?","simple-keyword?","simple-symbol?","slurp","some","some->","some->>","some-fn","some?","sort","sort-by","sorted-map","sorted-map-by","sorted-set","sorted-set-by","sorted?","special-symbol?","spit","split-at","split-with","str","string?","struct","struct-map","subs","subseq","subvec","supers","swap!","swap-vals!","symbol","symbol?","sync","tagged-literal","tagged-literal?","take","take-last","take-nth","take-while","test","the-ns","thread-bound?","time","to-array","to-array-2d","trampoline","transduce","transient","tree-seq","true?","type","unchecked-add","unchecked-add-int","unchecked-byte","unchecked-char","unchecked-dec","unchecked-dec-int","unchecked-divide-int","unchecked-double","unchecked-float","unchecked-inc","unchecked-inc-int","unchecked-int","unchecked-long","unchecked-multiply","unchecked-multiply-int","unchecked-negate","unchecked-negate-int","unchecked-remainder-int","unchecked-short","unchecked-subtract","unchecked-subtract-int","underive","unquote","unquote-splicing","unreduced","unsigned-bit-shift-right","update","update-in","update-proxy","uri?","use","uuid?","val","vals","var-get","var-set","var?","vary-meta","vec","vector","vector-of","vector?","volatile!","volatile?","vreset!","vswap!","when","when-first","when-let","when-not","when-some","while","with-bindings","with-bindings*","with-in-str","with-loading-context","with-local-vars","with-meta","with-open","with-out-str","with-precision","with-redefs","with-redefs-fn","xml-seq","zero?","zipmap"],o=y(r),i=y(a),c=y(s),d=y(["->","->>","as->","binding","bound-fn","case","catch","comment","cond","cond->","cond->>","condp","def","definterface","defmethod","defn","defmacro","defprotocol","defrecord","defstruct","deftype","do","doseq","dotimes","doto","extend","extend-protocol","extend-type","fn","for","future","if","if-let","if-not","if-some","let","letfn","locking","loop","ns","proxy","reify","struct-map","some->","some->>","try","when","when-first","when-let","when-not","when-some","while","with-bindings","with-bindings*","with-in-str","with-loading-context","with-local-vars","with-meta","with-open","with-out-str","with-precision","with-redefs","with-redefs-fn"]),l=/^(?:[\\\[\]\s"(),;@^`{}~]|$)/,u=/^(?:[+\-]?\d+(?:(?:N|(?:[eE][+\-]?\d+))|(?:\.?\d*(?:M|(?:[eE][+\-]?\d+))?)|\/\d+|[xX][0-9a-fA-F]+|r[0-9a-zA-Z]+)?(?=[\\\[\]\s"#'(),;@^`{}~]|$))/,p=/^(?:\\(?:backspace|formfeed|newline|return|space|tab|o[0-7]{3}|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{4}|.)?(?=[\\\[\]\s"(),;@^`{}~]|$))/,m=/^(?:(?:[^\\\/\[\]\d\s"#'(),;@^`{}~.][^\\\[\]\s"(),;@^`{}~.\/]*(?:\.[^\\\/\[\]\d\s"#'(),;@^`{}~.][^\\\[\]\s"(),;@^`{}~.\/]*)*\/)?(?:\/|[^\\\/\[\]\d\s"#'(),;@^`{}~][^\\\[\]\s"(),;@^`{}~]*)*(?=[\\\[\]\s"(),;@^`{}~]|$))/;function f(e,t){if(e.eatSpace()||e.eat(","))return["space",null];if(e.match(u))return[null,"number"];if(e.match(p))return[null,"string.special"];if(e.eat(/^"/))return(t.tokenize=h)(e,t);if(e.eat(/^[(\[{]/))return["open","bracket"];if(e.eat(/^[)\]}]/))return["close","bracket"];if(e.eat(/^;/))return e.skipToEnd(),["space","comment"];if(e.eat(/^[#'@^`~]/))return[null,"meta"];var n=e.match(m),r=n&&n[0];return r?"comment"===r&&"("===t.lastToken?(t.tokenize=b)(e,t):k(r,o)||":"===r.charAt(0)?["symbol","atom"]:k(r,i)||k(r,c)?["symbol","keyword"]:"("===t.lastToken?["symbol","builtin"]:["symbol","variable"]:(e.next(),e.eatWhile((function(e){return!k(e,l)})),[null,"error"])}function h(e,t){for(var n,r=!1;n=e.next();){if('"'===n&&!r){t.tokenize=f;break}r=!r&&"\\"===n}return[null,"string"]}function b(e,t){for(var n,r=1;n=e.next();)if(")"===n&&r--,"("===n&&r++,0===r){e.backUp(1),t.tokenize=f;break}return["space","comment"]}function y(e){for(var t={},n=0;n\", \"->>\", \"->ArrayChunk\", \"->Eduction\", \"->Vec\", \"->VecNode\",\n \"->VecSeq\", \"-cache-protocol-fn\", \"-reset-methods\", \"..\", \"/\", \"<\", \"<=\",\n \"=\", \"==\", \">\", \">=\", \"EMPTY-NODE\", \"Inst\", \"StackTraceElement->vec\",\n \"Throwable->map\", \"accessor\", \"aclone\", \"add-classpath\", \"add-watch\",\n \"agent\", \"agent-error\", \"agent-errors\", \"aget\", \"alength\", \"alias\",\n \"all-ns\", \"alter\", \"alter-meta!\", \"alter-var-root\", \"amap\", \"ancestors\",\n \"and\", \"any?\", \"apply\", \"areduce\", \"array-map\", \"as->\", \"aset\",\n \"aset-boolean\", \"aset-byte\", \"aset-char\", \"aset-double\", \"aset-float\",\n \"aset-int\", \"aset-long\", \"aset-short\", \"assert\", \"assoc\", \"assoc!\",\n \"assoc-in\", \"associative?\", \"atom\", \"await\", \"await-for\", \"await1\",\n \"bases\", \"bean\", \"bigdec\", \"bigint\", \"biginteger\", \"binding\", \"bit-and\",\n \"bit-and-not\", \"bit-clear\", \"bit-flip\", \"bit-not\", \"bit-or\", \"bit-set\",\n \"bit-shift-left\", \"bit-shift-right\", \"bit-test\", \"bit-xor\", \"boolean\",\n \"boolean-array\", \"boolean?\", \"booleans\", \"bound-fn\", \"bound-fn*\",\n \"bound?\", \"bounded-count\", \"butlast\", \"byte\", \"byte-array\", \"bytes\",\n \"bytes?\", \"case\", \"cast\", \"cat\", \"char\", \"char-array\",\n \"char-escape-string\", \"char-name-string\", \"char?\", \"chars\", \"chunk\",\n \"chunk-append\", \"chunk-buffer\", \"chunk-cons\", \"chunk-first\", \"chunk-next\",\n \"chunk-rest\", \"chunked-seq?\", \"class\", \"class?\", \"clear-agent-errors\",\n \"clojure-version\", \"coll?\", \"comment\", \"commute\", \"comp\", \"comparator\",\n \"compare\", \"compare-and-set!\", \"compile\", \"complement\", \"completing\",\n \"concat\", \"cond\", \"cond->\", \"cond->>\", \"condp\", \"conj\", \"conj!\", \"cons\",\n \"constantly\", \"construct-proxy\", \"contains?\", \"count\", \"counted?\",\n \"create-ns\", \"create-struct\", \"cycle\", \"dec\", \"dec'\", \"decimal?\",\n \"declare\", \"dedupe\", \"default-data-readers\", \"definline\", \"definterface\",\n \"defmacro\", \"defmethod\", \"defmulti\", \"defn\", \"defn-\", \"defonce\",\n \"defprotocol\", \"defrecord\", \"defstruct\", \"deftype\", \"delay\", \"delay?\",\n \"deliver\", \"denominator\", \"deref\", \"derive\", \"descendants\", \"destructure\",\n \"disj\", \"disj!\", \"dissoc\", \"dissoc!\", \"distinct\", \"distinct?\", \"doall\",\n \"dorun\", \"doseq\", \"dosync\", \"dotimes\", \"doto\", \"double\", \"double-array\",\n \"double?\", \"doubles\", \"drop\", \"drop-last\", \"drop-while\", \"eduction\",\n \"empty\", \"empty?\", \"ensure\", \"ensure-reduced\", \"enumeration-seq\",\n \"error-handler\", \"error-mode\", \"eval\", \"even?\", \"every-pred\", \"every?\",\n \"ex-data\", \"ex-info\", \"extend\", \"extend-protocol\", \"extend-type\",\n \"extenders\", \"extends?\", \"false?\", \"ffirst\", \"file-seq\", \"filter\",\n \"filterv\", \"find\", \"find-keyword\", \"find-ns\", \"find-protocol-impl\",\n \"find-protocol-method\", \"find-var\", \"first\", \"flatten\", \"float\",\n \"float-array\", \"float?\", \"floats\", \"flush\", \"fn\", \"fn?\", \"fnext\", \"fnil\",\n \"for\", \"force\", \"format\", \"frequencies\", \"future\", \"future-call\",\n \"future-cancel\", \"future-cancelled?\", \"future-done?\", \"future?\",\n \"gen-class\", \"gen-interface\", \"gensym\", \"get\", \"get-in\", \"get-method\",\n \"get-proxy-class\", \"get-thread-bindings\", \"get-validator\", \"group-by\",\n \"halt-when\", \"hash\", \"hash-combine\", \"hash-map\", \"hash-ordered-coll\",\n \"hash-set\", \"hash-unordered-coll\", \"ident?\", \"identical?\", \"identity\",\n \"if-let\", \"if-not\", \"if-some\", \"ifn?\", \"import\", \"in-ns\", \"inc\", \"inc'\",\n \"indexed?\", \"init-proxy\", \"inst-ms\", \"inst-ms*\", \"inst?\", \"instance?\",\n \"int\", \"int-array\", \"int?\", \"integer?\", \"interleave\", \"intern\",\n \"interpose\", \"into\", \"into-array\", \"ints\", \"io!\", \"isa?\", \"iterate\",\n \"iterator-seq\", \"juxt\", \"keep\", \"keep-indexed\", \"key\", \"keys\", \"keyword\",\n \"keyword?\", \"last\", \"lazy-cat\", \"lazy-seq\", \"let\", \"letfn\", \"line-seq\",\n \"list\", \"list*\", \"list?\", \"load\", \"load-file\", \"load-reader\",\n \"load-string\", \"loaded-libs\", \"locking\", \"long\", \"long-array\", \"longs\",\n \"loop\", \"macroexpand\", \"macroexpand-1\", \"make-array\", \"make-hierarchy\",\n \"map\", \"map-entry?\", \"map-indexed\", \"map?\", \"mapcat\", \"mapv\", \"max\",\n \"max-key\", \"memfn\", \"memoize\", \"merge\", \"merge-with\", \"meta\",\n \"method-sig\", \"methods\", \"min\", \"min-key\", \"mix-collection-hash\", \"mod\",\n \"munge\", \"name\", \"namespace\", \"namespace-munge\", \"nat-int?\", \"neg-int?\",\n \"neg?\", \"newline\", \"next\", \"nfirst\", \"nil?\", \"nnext\", \"not\", \"not-any?\",\n \"not-empty\", \"not-every?\", \"not=\", \"ns\", \"ns-aliases\", \"ns-imports\",\n \"ns-interns\", \"ns-map\", \"ns-name\", \"ns-publics\", \"ns-refers\",\n \"ns-resolve\", \"ns-unalias\", \"ns-unmap\", \"nth\", \"nthnext\", \"nthrest\",\n \"num\", \"number?\", \"numerator\", \"object-array\", \"odd?\", \"or\", \"parents\",\n \"partial\", \"partition\", \"partition-all\", \"partition-by\", \"pcalls\", \"peek\",\n \"persistent!\", \"pmap\", \"pop\", \"pop!\", \"pop-thread-bindings\", \"pos-int?\",\n \"pos?\", \"pr\", \"pr-str\", \"prefer-method\", \"prefers\",\n \"primitives-classnames\", \"print\", \"print-ctor\", \"print-dup\",\n \"print-method\", \"print-simple\", \"print-str\", \"printf\", \"println\",\n \"println-str\", \"prn\", \"prn-str\", \"promise\", \"proxy\",\n \"proxy-call-with-super\", \"proxy-mappings\", \"proxy-name\", \"proxy-super\",\n \"push-thread-bindings\", \"pvalues\", \"qualified-ident?\",\n \"qualified-keyword?\", \"qualified-symbol?\", \"quot\", \"rand\", \"rand-int\",\n \"rand-nth\", \"random-sample\", \"range\", \"ratio?\", \"rational?\",\n \"rationalize\", \"re-find\", \"re-groups\", \"re-matcher\", \"re-matches\",\n \"re-pattern\", \"re-seq\", \"read\", \"read-line\", \"read-string\",\n \"reader-conditional\", \"reader-conditional?\", \"realized?\", \"record?\",\n \"reduce\", \"reduce-kv\", \"reduced\", \"reduced?\", \"reductions\", \"ref\",\n \"ref-history-count\", \"ref-max-history\", \"ref-min-history\", \"ref-set\",\n \"refer\", \"refer-clojure\", \"reify\", \"release-pending-sends\", \"rem\",\n \"remove\", \"remove-all-methods\", \"remove-method\", \"remove-ns\",\n \"remove-watch\", \"repeat\", \"repeatedly\", \"replace\", \"replicate\", \"require\",\n \"reset!\", \"reset-meta!\", \"reset-vals!\", \"resolve\", \"rest\",\n \"restart-agent\", \"resultset-seq\", \"reverse\", \"reversible?\", \"rseq\",\n \"rsubseq\", \"run!\", \"satisfies?\", \"second\", \"select-keys\", \"send\",\n \"send-off\", \"send-via\", \"seq\", \"seq?\", \"seqable?\", \"seque\", \"sequence\",\n \"sequential?\", \"set\", \"set-agent-send-executor!\",\n \"set-agent-send-off-executor!\", \"set-error-handler!\", \"set-error-mode!\",\n \"set-validator!\", \"set?\", \"short\", \"short-array\", \"shorts\", \"shuffle\",\n \"shutdown-agents\", \"simple-ident?\", \"simple-keyword?\", \"simple-symbol?\",\n \"slurp\", \"some\", \"some->\", \"some->>\", \"some-fn\", \"some?\", \"sort\",\n \"sort-by\", \"sorted-map\", \"sorted-map-by\", \"sorted-set\", \"sorted-set-by\",\n \"sorted?\", \"special-symbol?\", \"spit\", \"split-at\", \"split-with\", \"str\",\n \"string?\", \"struct\", \"struct-map\", \"subs\", \"subseq\", \"subvec\", \"supers\",\n \"swap!\", \"swap-vals!\", \"symbol\", \"symbol?\", \"sync\", \"tagged-literal\",\n \"tagged-literal?\", \"take\", \"take-last\", \"take-nth\", \"take-while\", \"test\",\n \"the-ns\", \"thread-bound?\", \"time\", \"to-array\", \"to-array-2d\",\n \"trampoline\", \"transduce\", \"transient\", \"tree-seq\", \"true?\", \"type\",\n \"unchecked-add\", \"unchecked-add-int\", \"unchecked-byte\", \"unchecked-char\",\n \"unchecked-dec\", \"unchecked-dec-int\", \"unchecked-divide-int\",\n \"unchecked-double\", \"unchecked-float\", \"unchecked-inc\",\n \"unchecked-inc-int\", \"unchecked-int\", \"unchecked-long\",\n \"unchecked-multiply\", \"unchecked-multiply-int\", \"unchecked-negate\",\n \"unchecked-negate-int\", \"unchecked-remainder-int\", \"unchecked-short\",\n \"unchecked-subtract\", \"unchecked-subtract-int\", \"underive\", \"unquote\",\n \"unquote-splicing\", \"unreduced\", \"unsigned-bit-shift-right\", \"update\",\n \"update-in\", \"update-proxy\", \"uri?\", \"use\", \"uuid?\", \"val\", \"vals\",\n \"var-get\", \"var-set\", \"var?\", \"vary-meta\", \"vec\", \"vector\", \"vector-of\",\n \"vector?\", \"volatile!\", \"volatile?\", \"vreset!\", \"vswap!\", \"when\",\n \"when-first\", \"when-let\", \"when-not\", \"when-some\", \"while\",\n \"with-bindings\", \"with-bindings*\", \"with-in-str\", \"with-loading-context\",\n \"with-local-vars\", \"with-meta\", \"with-open\", \"with-out-str\",\n \"with-precision\", \"with-redefs\", \"with-redefs-fn\", \"xml-seq\", \"zero?\",\n \"zipmap\"];\nvar haveBodyParameter = [\n \"->\", \"->>\", \"as->\", \"binding\", \"bound-fn\", \"case\", \"catch\", \"comment\",\n \"cond\", \"cond->\", \"cond->>\", \"condp\", \"def\", \"definterface\", \"defmethod\",\n \"defn\", \"defmacro\", \"defprotocol\", \"defrecord\", \"defstruct\", \"deftype\",\n \"do\", \"doseq\", \"dotimes\", \"doto\", \"extend\", \"extend-protocol\",\n \"extend-type\", \"fn\", \"for\", \"future\", \"if\", \"if-let\", \"if-not\", \"if-some\",\n \"let\", \"letfn\", \"locking\", \"loop\", \"ns\", \"proxy\", \"reify\", \"struct-map\",\n \"some->\", \"some->>\", \"try\", \"when\", \"when-first\", \"when-let\", \"when-not\",\n \"when-some\", \"while\", \"with-bindings\", \"with-bindings*\", \"with-in-str\",\n \"with-loading-context\", \"with-local-vars\", \"with-meta\", \"with-open\",\n \"with-out-str\", \"with-precision\", \"with-redefs\", \"with-redefs-fn\"];\n\nvar atom = createLookupMap(atoms);\nvar specialForm = createLookupMap(specialForms);\nvar coreSymbol = createLookupMap(coreSymbols);\nvar hasBodyParameter = createLookupMap(haveBodyParameter);\nvar delimiter = /^(?:[\\\\\\[\\]\\s\"(),;@^`{}~]|$)/;\nvar numberLiteral = /^(?:[+\\-]?\\d+(?:(?:N|(?:[eE][+\\-]?\\d+))|(?:\\.?\\d*(?:M|(?:[eE][+\\-]?\\d+))?)|\\/\\d+|[xX][0-9a-fA-F]+|r[0-9a-zA-Z]+)?(?=[\\\\\\[\\]\\s\"#'(),;@^`{}~]|$))/;\nvar characterLiteral = /^(?:\\\\(?:backspace|formfeed|newline|return|space|tab|o[0-7]{3}|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{4}|.)?(?=[\\\\\\[\\]\\s\"(),;@^`{}~]|$))/;\n\n// simple-namespace := /^[^\\\\\\/\\[\\]\\d\\s\"#'(),;@^`{}~.][^\\\\\\[\\]\\s\"(),;@^`{}~.\\/]*/\n// simple-symbol := /^(?:\\/|[^\\\\\\/\\[\\]\\d\\s\"#'(),;@^`{}~][^\\\\\\[\\]\\s\"(),;@^`{}~]*)/\n// qualified-symbol := ((<.>)*>)?\nvar qualifiedSymbol = /^(?:(?:[^\\\\\\/\\[\\]\\d\\s\"#'(),;@^`{}~.][^\\\\\\[\\]\\s\"(),;@^`{}~.\\/]*(?:\\.[^\\\\\\/\\[\\]\\d\\s\"#'(),;@^`{}~.][^\\\\\\[\\]\\s\"(),;@^`{}~.\\/]*)*\\/)?(?:\\/|[^\\\\\\/\\[\\]\\d\\s\"#'(),;@^`{}~][^\\\\\\[\\]\\s\"(),;@^`{}~]*)*(?=[\\\\\\[\\]\\s\"(),;@^`{}~]|$))/;\n\nfunction base(stream, state) {\n if (stream.eatSpace() || stream.eat(\",\")) return [\"space\", null];\n if (stream.match(numberLiteral)) return [null, \"number\"];\n if (stream.match(characterLiteral)) return [null, \"string.special\"];\n if (stream.eat(/^\"/)) return (state.tokenize = inString)(stream, state);\n if (stream.eat(/^[(\\[{]/)) return [\"open\", \"bracket\"];\n if (stream.eat(/^[)\\]}]/)) return [\"close\", \"bracket\"];\n if (stream.eat(/^;/)) {stream.skipToEnd(); return [\"space\", \"comment\"];}\n if (stream.eat(/^[#'@^`~]/)) return [null, \"meta\"];\n\n var matches = stream.match(qualifiedSymbol);\n var symbol = matches && matches[0];\n\n if (!symbol) {\n // advance stream by at least one character so we don't get stuck.\n stream.next();\n stream.eatWhile(function (c) {return !is(c, delimiter);});\n return [null, \"error\"];\n }\n\n if (symbol === \"comment\" && state.lastToken === \"(\")\n return (state.tokenize = inComment)(stream, state);\n if (is(symbol, atom) || symbol.charAt(0) === \":\") return [\"symbol\", \"atom\"];\n if (is(symbol, specialForm) || is(symbol, coreSymbol)) return [\"symbol\", \"keyword\"];\n if (state.lastToken === \"(\") return [\"symbol\", \"builtin\"]; // other operator\n\n return [\"symbol\", \"variable\"];\n}\n\nfunction inString(stream, state) {\n var escaped = false, next;\n\n while (next = stream.next()) {\n if (next === \"\\\"\" && !escaped) {state.tokenize = base; break;}\n escaped = !escaped && next === \"\\\\\";\n }\n\n return [null, \"string\"];\n}\n\nfunction inComment(stream, state) {\n var parenthesisCount = 1;\n var next;\n\n while (next = stream.next()) {\n if (next === \")\") parenthesisCount--;\n if (next === \"(\") parenthesisCount++;\n if (parenthesisCount === 0) {\n stream.backUp(1);\n state.tokenize = base;\n break;\n }\n }\n\n return [\"space\", \"comment\"];\n}\n\nfunction createLookupMap(words) {\n var obj = {};\n\n for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n\n return obj;\n}\n\nfunction is(value, test) {\n if (test instanceof RegExp) return test.test(value);\n if (test instanceof Object) return test.propertyIsEnumerable(value);\n}\n\nexport const clojure = {\n name: \"clojure\",\n startState: function () {\n return {\n ctx: {prev: null, start: 0, indentTo: 0},\n lastToken: null,\n tokenize: base\n };\n },\n\n token: function (stream, state) {\n if (stream.sol() && (typeof state.ctx.indentTo !== \"number\"))\n state.ctx.indentTo = state.ctx.start + 1;\n\n var typeStylePair = state.tokenize(stream, state);\n var type = typeStylePair[0];\n var style = typeStylePair[1];\n var current = stream.current();\n\n if (type !== \"space\") {\n if (state.lastToken === \"(\" && state.ctx.indentTo === null) {\n if (type === \"symbol\" && is(current, hasBodyParameter))\n state.ctx.indentTo = state.ctx.start + stream.indentUnit;\n else state.ctx.indentTo = \"next\";\n } else if (state.ctx.indentTo === \"next\") {\n state.ctx.indentTo = stream.column();\n }\n\n state.lastToken = current;\n }\n\n if (type === \"open\")\n state.ctx = {prev: state.ctx, start: stream.column(), indentTo: null};\n else if (type === \"close\") state.ctx = state.ctx.prev || state.ctx;\n\n return style;\n },\n\n indent: function (state) {\n var i = state.ctx.indentTo;\n\n return (typeof i === \"number\") ?\n i :\n state.ctx.start + 1;\n },\n\n languageData: {\n closeBrackets: {brackets: [\"(\", \"[\", \"{\", '\"']},\n commentTokens: {line: \";;\"},\n autocomplete: [].concat(atoms, specialForms, coreSymbols)\n }\n};\n"],"names":["atoms","specialForms","coreSymbols","atom","createLookupMap","specialForm","coreSymbol","hasBodyParameter","delimiter","numberLiteral","characterLiteral","qualifiedSymbol","base","stream","state","eatSpace","eat","match","tokenize","inString","skipToEnd","matches","symbol","lastToken","inComment","is","charAt","next","eatWhile","c","escaped","parenthesisCount","backUp","words","obj","i","length","value","test","RegExp","Object","propertyIsEnumerable","clojure","name","startState","ctx","prev","start","indentTo","token","sol","typeStylePair","type","style","current","indentUnit","column","indent","languageData","closeBrackets","brackets","commentTokens","line","autocomplete","concat"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/5815.index.js b/book/_build/html/_static/5815.index.js
new file mode 100644
index 0000000..54c7671
--- /dev/null
+++ b/book/_build/html/_static/5815.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[5815],{65815:(e,t,n)=>{function r(e,t,n){return function(r,i){for(;!r.eol();){if(r.match(t)){i.tokenize=a;break}r.next()}return n&&(i.tokenize=n),e}}function i(e){return function(t,n){for(;!t.eol();)t.next();return n.tokenize=a,e}}function a(e,t){function n(n){return t.tokenize=n,n(e,t)}var u=e.sol(),o=e.next();switch(o){case"{":return e.eat("/"),e.eatSpace(),e.eatWhile(/[^\s\u00a0=\"\'\/?(}]/),t.tokenize=s,"tag";case"_":if(e.eat("_"))return n(r("strong","__",a));break;case"'":if(e.eat("'"))return n(r("em","''",a));break;case"(":if(e.eat("("))return n(r("link","))",a));break;case"[":return n(r("url","]",a));case"|":if(e.eat("|"))return n(r("comment","||"));break;case"-":if(e.eat("="))return n(r("header string","=-",a));if(e.eat("-"))return n(r("error tw-deleted","--",a));break;case"=":if(e.match("=="))return n(r("tw-underline","===",a));break;case":":if(e.eat(":"))return n(r("comment","::"));break;case"^":return n(r("tw-box","^"));case"~":if(e.match("np~"))return n(r("meta","~/np~"))}if(u)switch(o){case"!":return e.match("!!!!!")||e.match("!!!!")||e.match("!!!")||e.match("!!"),n(i("header string"));case"*":case"#":case"+":return n(i("tw-listitem bracket"))}return null}var u,o,c,f;function s(e,t){var n,r=e.next(),i=e.peek();return"}"==r?(t.tokenize=a,"tag"):"("==r||")"==r?"bracket":"="==r?(o="equals",">"==i&&(e.next(),i=e.peek()),/[\'\"]/.test(i)||(t.tokenize=function(e,t){for(;!e.eol();){var n=e.next(),r=e.peek();if(" "==n||","==n||/[ )}]/.test(r)){t.tokenize=s;break}}return"string"}),"operator"):/[\'\"]/.test(r)?(t.tokenize=(n=r,function(e,t){for(;!e.eol();)if(e.next()==n){t.tokenize=s;break}return"string"}),t.tokenize(e,t)):(e.eatWhile(/[^\s\u00a0=\"\'\/?]/),"keyword")}function l(){for(var e=arguments.length-1;e>=0;e--)c.cc.push(arguments[e])}function k(){return l.apply(null,arguments),!0}function d(e,t){var n=c.context&&c.context.noIndent;c.context={prev:c.context,pluginName:e,indent:c.indented,startOfLine:t,noIndent:n}}function p(){c.context&&(c.context=c.context.prev)}function g(e){if("openPlugin"==e)return c.pluginName=u,k(m,(n=c.startOfLine,function(e){return"selfclosePlugin"==e||"endPlugin"==e?k():"endPlugin"==e?(d(c.pluginName,n),k()):k()}));if("closePlugin"==e){var t=!1;return c.context?(t=c.context.pluginName!=u,p()):t=!0,t&&(f="error"),k(function(e){return function(t){return e&&(f="error"),"endPlugin"==t?k():l()}}(t))}return"string"==e?(c.context&&"!cdata"==c.context.name||d("!cdata"),c.tokenize==a&&p(),k()):k();var n}function m(e){return"keyword"==e?(f="attribute",k(m)):"equals"==e?k(x,m):l()}function x(e){return"keyword"==e?(f="string",k()):"string"==e?k(h):l()}function h(e){return"string"==e?k(h):l()}n.r(t),n.d(t,{tiki:()=>b});const b={name:"tiki",startState:function(){return{tokenize:a,cc:[],indented:0,startOfLine:!0,pluginName:null,context:null}},token:function(e,t){if(e.sol()&&(t.startOfLine=!0,t.indented=e.indentation()),e.eatSpace())return null;f=o=u=null;var n=t.tokenize(e,t);if((n||o)&&"comment"!=n)for(c=t;!(t.cc.pop()||g)(o||n););return t.startOfLine=!1,f||n},indent:function(e,t,n){var r=e.context;if(r&&r.noIndent)return 0;for(r&&/^{\//.test(t)&&(r=r.prev);r&&!r.startOfLine;)r=r.prev;return r?r.indent+n.unit:0}}}}]);
+//# sourceMappingURL=5815.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/5815.index.js.map b/book/_build/html/_static/5815.index.js.map
new file mode 100644
index 0000000..68fc1b8
--- /dev/null
+++ b/book/_build/html/_static/5815.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"5815.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/tiki.js"],"sourcesContent":["function inBlock(style, terminator, returnTokenizer) {\n return function(stream, state) {\n while (!stream.eol()) {\n if (stream.match(terminator)) {\n state.tokenize = inText;\n break;\n }\n stream.next();\n }\n\n if (returnTokenizer) state.tokenize = returnTokenizer;\n\n return style;\n };\n}\n\nfunction inLine(style) {\n return function(stream, state) {\n while(!stream.eol()) {\n stream.next();\n }\n state.tokenize = inText;\n return style;\n };\n}\n\nfunction inText(stream, state) {\n function chain(parser) {\n state.tokenize = parser;\n return parser(stream, state);\n }\n\n var sol = stream.sol();\n var ch = stream.next();\n\n //non start of line\n switch (ch) { //switch is generally much faster than if, so it is used here\n case \"{\": //plugin\n stream.eat(\"/\");\n stream.eatSpace();\n stream.eatWhile(/[^\\s\\u00a0=\\\"\\'\\/?(}]/);\n state.tokenize = inPlugin;\n return \"tag\";\n case \"_\": //bold\n if (stream.eat(\"_\"))\n return chain(inBlock(\"strong\", \"__\", inText));\n break;\n case \"'\": //italics\n if (stream.eat(\"'\"))\n return chain(inBlock(\"em\", \"''\", inText));\n break;\n case \"(\":// Wiki Link\n if (stream.eat(\"(\"))\n return chain(inBlock(\"link\", \"))\", inText));\n break;\n case \"[\":// Weblink\n return chain(inBlock(\"url\", \"]\", inText));\n break;\n case \"|\": //table\n if (stream.eat(\"|\"))\n return chain(inBlock(\"comment\", \"||\"));\n break;\n case \"-\":\n if (stream.eat(\"=\")) {//titleBar\n return chain(inBlock(\"header string\", \"=-\", inText));\n } else if (stream.eat(\"-\")) {//deleted\n return chain(inBlock(\"error tw-deleted\", \"--\", inText));\n }\n break;\n case \"=\": //underline\n if (stream.match(\"==\"))\n return chain(inBlock(\"tw-underline\", \"===\", inText));\n break;\n case \":\":\n if (stream.eat(\":\"))\n return chain(inBlock(\"comment\", \"::\"));\n break;\n case \"^\": //box\n return chain(inBlock(\"tw-box\", \"^\"));\n break;\n case \"~\": //np\n if (stream.match(\"np~\"))\n return chain(inBlock(\"meta\", \"~/np~\"));\n break;\n }\n\n //start of line types\n if (sol) {\n switch (ch) {\n case \"!\": //header at start of line\n if (stream.match('!!!!!')) {\n return chain(inLine(\"header string\"));\n } else if (stream.match('!!!!')) {\n return chain(inLine(\"header string\"));\n } else if (stream.match('!!!')) {\n return chain(inLine(\"header string\"));\n } else if (stream.match('!!')) {\n return chain(inLine(\"header string\"));\n } else {\n return chain(inLine(\"header string\"));\n }\n break;\n case \"*\": //unordered list line item, or at start of line\n case \"#\": //ordered list line item, or at start of line\n case \"+\": //ordered list line item, or at start of line\n return chain(inLine(\"tw-listitem bracket\"));\n break;\n }\n }\n\n //stream.eatWhile(/[&{]/); was eating up plugins, turned off to act less like html and more like tiki\n return null;\n}\n\n// Return variables for tokenizers\nvar pluginName, type;\nfunction inPlugin(stream, state) {\n var ch = stream.next();\n var peek = stream.peek();\n\n if (ch == \"}\") {\n state.tokenize = inText;\n //type = ch == \")\" ? \"endPlugin\" : \"selfclosePlugin\"; inPlugin\n return \"tag\";\n } else if (ch == \"(\" || ch == \")\") {\n return \"bracket\";\n } else if (ch == \"=\") {\n type = \"equals\";\n\n if (peek == \">\") {\n stream.next();\n peek = stream.peek();\n }\n\n //here we detect values directly after equal character with no quotes\n if (!/[\\'\\\"]/.test(peek)) {\n state.tokenize = inAttributeNoQuote();\n }\n //end detect values\n\n return \"operator\";\n } else if (/[\\'\\\"]/.test(ch)) {\n state.tokenize = inAttribute(ch);\n return state.tokenize(stream, state);\n } else {\n stream.eatWhile(/[^\\s\\u00a0=\\\"\\'\\/?]/);\n return \"keyword\";\n }\n}\n\nfunction inAttribute(quote) {\n return function(stream, state) {\n while (!stream.eol()) {\n if (stream.next() == quote) {\n state.tokenize = inPlugin;\n break;\n }\n }\n return \"string\";\n };\n}\n\nfunction inAttributeNoQuote() {\n return function(stream, state) {\n while (!stream.eol()) {\n var ch = stream.next();\n var peek = stream.peek();\n if (ch == \" \" || ch == \",\" || /[ )}]/.test(peek)) {\n state.tokenize = inPlugin;\n break;\n }\n }\n return \"string\";\n };\n}\n\nvar curState, setStyle;\nfunction pass() {\n for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);\n}\n\nfunction cont() {\n pass.apply(null, arguments);\n return true;\n}\n\nfunction pushContext(pluginName, startOfLine) {\n var noIndent = curState.context && curState.context.noIndent;\n curState.context = {\n prev: curState.context,\n pluginName: pluginName,\n indent: curState.indented,\n startOfLine: startOfLine,\n noIndent: noIndent\n };\n}\n\nfunction popContext() {\n if (curState.context) curState.context = curState.context.prev;\n}\n\nfunction element(type) {\n if (type == \"openPlugin\") {curState.pluginName = pluginName; return cont(attributes, endplugin(curState.startOfLine));}\n else if (type == \"closePlugin\") {\n var err = false;\n if (curState.context) {\n err = curState.context.pluginName != pluginName;\n popContext();\n } else {\n err = true;\n }\n if (err) setStyle = \"error\";\n return cont(endcloseplugin(err));\n }\n else if (type == \"string\") {\n if (!curState.context || curState.context.name != \"!cdata\") pushContext(\"!cdata\");\n if (curState.tokenize == inText) popContext();\n return cont();\n }\n else return cont();\n}\n\nfunction endplugin(startOfLine) {\n return function(type) {\n if (\n type == \"selfclosePlugin\" ||\n type == \"endPlugin\"\n )\n return cont();\n if (type == \"endPlugin\") {pushContext(curState.pluginName, startOfLine); return cont();}\n return cont();\n };\n}\n\nfunction endcloseplugin(err) {\n return function(type) {\n if (err) setStyle = \"error\";\n if (type == \"endPlugin\") return cont();\n return pass();\n };\n}\n\nfunction attributes(type) {\n if (type == \"keyword\") {setStyle = \"attribute\"; return cont(attributes);}\n if (type == \"equals\") return cont(attvalue, attributes);\n return pass();\n}\nfunction attvalue(type) {\n if (type == \"keyword\") {setStyle = \"string\"; return cont();}\n if (type == \"string\") return cont(attvaluemaybe);\n return pass();\n}\nfunction attvaluemaybe(type) {\n if (type == \"string\") return cont(attvaluemaybe);\n else return pass();\n}\nexport const tiki = {\n name: \"tiki\",\n startState: function() {\n return {tokenize: inText, cc: [], indented: 0, startOfLine: true, pluginName: null, context: null};\n },\n token: function(stream, state) {\n if (stream.sol()) {\n state.startOfLine = true;\n state.indented = stream.indentation();\n }\n if (stream.eatSpace()) return null;\n\n setStyle = type = pluginName = null;\n var style = state.tokenize(stream, state);\n if ((style || type) && style != \"comment\") {\n curState = state;\n while (true) {\n var comb = state.cc.pop() || element;\n if (comb(type || style)) break;\n }\n }\n state.startOfLine = false;\n return setStyle || style;\n },\n indent: function(state, textAfter, cx) {\n var context = state.context;\n if (context && context.noIndent) return 0;\n if (context && /^{\\//.test(textAfter))\n context = context.prev;\n while (context && !context.startOfLine)\n context = context.prev;\n if (context) return context.indent + cx.unit;\n else return 0;\n }\n};\n"],"names":["inBlock","style","terminator","returnTokenizer","stream","state","eol","match","tokenize","inText","next","inLine","chain","parser","sol","ch","eat","eatSpace","eatWhile","inPlugin","pluginName","type","curState","setStyle","quote","peek","test","pass","i","arguments","length","cc","push","cont","apply","pushContext","startOfLine","noIndent","context","prev","indent","indented","popContext","element","attributes","err","endcloseplugin","name","attvalue","attvaluemaybe","tiki","startState","token","indentation","pop","textAfter","cx","unit"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/5836.index.js b/book/_build/html/_static/5836.index.js
new file mode 100644
index 0000000..5c5a94d
--- /dev/null
+++ b/book/_build/html/_static/5836.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[5836],{55836:(I,_,R)=>{R.r(_),R.d(_,{ntriples:()=>t});var e={PRE_SUBJECT:0,WRITING_SUB_URI:1,WRITING_BNODE_URI:2,PRE_PRED:3,WRITING_PRED_URI:4,PRE_OBJ:5,WRITING_OBJ_URI:6,WRITING_OBJ_BNODE:7,WRITING_OBJ_LITERAL:8,WRITING_LIT_LANG:9,WRITING_LIT_TYPE:10,POST_OBJ:11,ERROR:12};function n(I,_){var R,n=I.location;R=n==e.PRE_SUBJECT&&"<"==_?e.WRITING_SUB_URI:n==e.PRE_SUBJECT&&"_"==_?e.WRITING_BNODE_URI:n==e.PRE_PRED&&"<"==_?e.WRITING_PRED_URI:n==e.PRE_OBJ&&"<"==_?e.WRITING_OBJ_URI:n==e.PRE_OBJ&&"_"==_?e.WRITING_OBJ_BNODE:n==e.PRE_OBJ&&'"'==_?e.WRITING_OBJ_LITERAL:n==e.WRITING_SUB_URI&&">"==_||n==e.WRITING_BNODE_URI&&" "==_?e.PRE_PRED:n==e.WRITING_PRED_URI&&">"==_?e.PRE_OBJ:n==e.WRITING_OBJ_URI&&">"==_||n==e.WRITING_OBJ_BNODE&&" "==_||n==e.WRITING_OBJ_LITERAL&&'"'==_||n==e.WRITING_LIT_LANG&&" "==_||n==e.WRITING_LIT_TYPE&&">"==_?e.POST_OBJ:n==e.WRITING_OBJ_LITERAL&&"@"==_?e.WRITING_LIT_LANG:n==e.WRITING_OBJ_LITERAL&&"^"==_?e.WRITING_LIT_TYPE:" "!=_||n!=e.PRE_SUBJECT&&n!=e.PRE_PRED&&n!=e.PRE_OBJ&&n!=e.POST_OBJ?n==e.POST_OBJ&&"."==_?e.PRE_SUBJECT:e.ERROR:n,I.location=R}const t={name:"ntriples",startState:function(){return{location:e.PRE_SUBJECT,uris:[],anchors:[],bnodes:[],langs:[],types:[]}},token:function(I,_){var R=I.next();if("<"==R){n(_,R);var e="";return I.eatWhile((function(I){return"#"!=I&&">"!=I&&(e+=I,!0)})),_.uris.push(e),I.match("#",!1)||(I.next(),n(_,">")),"variable"}if("#"==R){var t="";return I.eatWhile((function(I){return">"!=I&&" "!=I&&(t+=I,!0)})),_.anchors.push(t),"url"}if(">"==R)return n(_,">"),"variable";if("_"==R){n(_,R);var r="";return I.eatWhile((function(I){return" "!=I&&(r+=I,!0)})),_.bnodes.push(r),I.next(),n(_," "),"builtin"}if('"'==R)return n(_,R),I.eatWhile((function(I){return'"'!=I})),I.next(),"@"!=I.peek()&&"^"!=I.peek()&&n(_,'"'),"string";if("@"==R){n(_,"@");var T="";return I.eatWhile((function(I){return" "!=I&&(T+=I,!0)})),_.langs.push(T),I.next(),n(_," "),"string.special"}if("^"==R){I.next(),n(_,"^");var E="";return I.eatWhile((function(I){return">"!=I&&(E+=I,!0)})),_.types.push(E),I.next(),n(_,">"),"variable"}" "==R&&n(_,R),"."==R&&n(_,R)}}}}]);
+//# sourceMappingURL=5836.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/5836.index.js.map b/book/_build/html/_static/5836.index.js.map
new file mode 100644
index 0000000..0525549
--- /dev/null
+++ b/book/_build/html/_static/5836.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"5836.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/ntriples.js"],"sourcesContent":["var Location = {\n PRE_SUBJECT : 0,\n WRITING_SUB_URI : 1,\n WRITING_BNODE_URI : 2,\n PRE_PRED : 3,\n WRITING_PRED_URI : 4,\n PRE_OBJ : 5,\n WRITING_OBJ_URI : 6,\n WRITING_OBJ_BNODE : 7,\n WRITING_OBJ_LITERAL : 8,\n WRITING_LIT_LANG : 9,\n WRITING_LIT_TYPE : 10,\n POST_OBJ : 11,\n ERROR : 12\n};\nfunction transitState(currState, c) {\n var currLocation = currState.location;\n var ret;\n\n // Opening.\n if (currLocation == Location.PRE_SUBJECT && c == '<') ret = Location.WRITING_SUB_URI;\n else if(currLocation == Location.PRE_SUBJECT && c == '_') ret = Location.WRITING_BNODE_URI;\n else if(currLocation == Location.PRE_PRED && c == '<') ret = Location.WRITING_PRED_URI;\n else if(currLocation == Location.PRE_OBJ && c == '<') ret = Location.WRITING_OBJ_URI;\n else if(currLocation == Location.PRE_OBJ && c == '_') ret = Location.WRITING_OBJ_BNODE;\n else if(currLocation == Location.PRE_OBJ && c == '\"') ret = Location.WRITING_OBJ_LITERAL;\n\n // Closing.\n else if(currLocation == Location.WRITING_SUB_URI && c == '>') ret = Location.PRE_PRED;\n else if(currLocation == Location.WRITING_BNODE_URI && c == ' ') ret = Location.PRE_PRED;\n else if(currLocation == Location.WRITING_PRED_URI && c == '>') ret = Location.PRE_OBJ;\n else if(currLocation == Location.WRITING_OBJ_URI && c == '>') ret = Location.POST_OBJ;\n else if(currLocation == Location.WRITING_OBJ_BNODE && c == ' ') ret = Location.POST_OBJ;\n else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '\"') ret = Location.POST_OBJ;\n else if(currLocation == Location.WRITING_LIT_LANG && c == ' ') ret = Location.POST_OBJ;\n else if(currLocation == Location.WRITING_LIT_TYPE && c == '>') ret = Location.POST_OBJ;\n\n // Closing typed and language literal.\n else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '@') ret = Location.WRITING_LIT_LANG;\n else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '^') ret = Location.WRITING_LIT_TYPE;\n\n // Spaces.\n else if( c == ' ' &&\n (\n currLocation == Location.PRE_SUBJECT ||\n currLocation == Location.PRE_PRED ||\n currLocation == Location.PRE_OBJ ||\n currLocation == Location.POST_OBJ\n )\n ) ret = currLocation;\n\n // Reset.\n else if(currLocation == Location.POST_OBJ && c == '.') ret = Location.PRE_SUBJECT;\n\n // Error\n else ret = Location.ERROR;\n\n currState.location=ret;\n}\n\nexport const ntriples = {\n name: \"ntriples\",\n startState: function() {\n return {\n location : Location.PRE_SUBJECT,\n uris : [],\n anchors : [],\n bnodes : [],\n langs : [],\n types : []\n };\n },\n token: function(stream, state) {\n var ch = stream.next();\n if(ch == '<') {\n transitState(state, ch);\n var parsedURI = '';\n stream.eatWhile( function(c) { if( c != '#' && c != '>' ) { parsedURI += c; return true; } return false;} );\n state.uris.push(parsedURI);\n if( stream.match('#', false) ) return 'variable';\n stream.next();\n transitState(state, '>');\n return 'variable';\n }\n if(ch == '#') {\n var parsedAnchor = '';\n stream.eatWhile(function(c) { if(c != '>' && c != ' ') { parsedAnchor+= c; return true; } return false;});\n state.anchors.push(parsedAnchor);\n return 'url';\n }\n if(ch == '>') {\n transitState(state, '>');\n return 'variable';\n }\n if(ch == '_') {\n transitState(state, ch);\n var parsedBNode = '';\n stream.eatWhile(function(c) { if( c != ' ' ) { parsedBNode += c; return true; } return false;});\n state.bnodes.push(parsedBNode);\n stream.next();\n transitState(state, ' ');\n return 'builtin';\n }\n if(ch == '\"') {\n transitState(state, ch);\n stream.eatWhile( function(c) { return c != '\"'; } );\n stream.next();\n if( stream.peek() != '@' && stream.peek() != '^' ) {\n transitState(state, '\"');\n }\n return 'string';\n }\n if( ch == '@' ) {\n transitState(state, '@');\n var parsedLang = '';\n stream.eatWhile(function(c) { if( c != ' ' ) { parsedLang += c; return true; } return false;});\n state.langs.push(parsedLang);\n stream.next();\n transitState(state, ' ');\n return 'string.special';\n }\n if( ch == '^' ) {\n stream.next();\n transitState(state, '^');\n var parsedType = '';\n stream.eatWhile(function(c) { if( c != '>' ) { parsedType += c; return true; } return false;} );\n state.types.push(parsedType);\n stream.next();\n transitState(state, '>');\n return 'variable';\n }\n if( ch == ' ' ) {\n transitState(state, ch);\n }\n if( ch == '.' ) {\n transitState(state, ch);\n }\n }\n};\n"],"names":["Location","PRE_SUBJECT","WRITING_SUB_URI","WRITING_BNODE_URI","PRE_PRED","WRITING_PRED_URI","PRE_OBJ","WRITING_OBJ_URI","WRITING_OBJ_BNODE","WRITING_OBJ_LITERAL","WRITING_LIT_LANG","WRITING_LIT_TYPE","POST_OBJ","ERROR","transitState","currState","c","ret","currLocation","location","ntriples","name","startState","uris","anchors","bnodes","langs","types","token","stream","state","ch","next","parsedURI","eatWhile","push","match","parsedAnchor","parsedBNode","peek","parsedLang","parsedType"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/5950.index.js b/book/_build/html/_static/5950.index.js
new file mode 100644
index 0000000..54451a9
--- /dev/null
+++ b/book/_build/html/_static/5950.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[5950],{15950:(i,l,e)=>{function a(i){var l=[],e="",a={".abort":"builtin",".align":"builtin",".altmacro":"builtin",".ascii":"builtin",".asciz":"builtin",".balign":"builtin",".balignw":"builtin",".balignl":"builtin",".bundle_align_mode":"builtin",".bundle_lock":"builtin",".bundle_unlock":"builtin",".byte":"builtin",".cfi_startproc":"builtin",".comm":"builtin",".data":"builtin",".def":"builtin",".desc":"builtin",".dim":"builtin",".double":"builtin",".eject":"builtin",".else":"builtin",".elseif":"builtin",".end":"builtin",".endef":"builtin",".endfunc":"builtin",".endif":"builtin",".equ":"builtin",".equiv":"builtin",".eqv":"builtin",".err":"builtin",".error":"builtin",".exitm":"builtin",".extern":"builtin",".fail":"builtin",".file":"builtin",".fill":"builtin",".float":"builtin",".func":"builtin",".global":"builtin",".gnu_attribute":"builtin",".hidden":"builtin",".hword":"builtin",".ident":"builtin",".if":"builtin",".incbin":"builtin",".include":"builtin",".int":"builtin",".internal":"builtin",".irp":"builtin",".irpc":"builtin",".lcomm":"builtin",".lflags":"builtin",".line":"builtin",".linkonce":"builtin",".list":"builtin",".ln":"builtin",".loc":"builtin",".loc_mark_labels":"builtin",".local":"builtin",".long":"builtin",".macro":"builtin",".mri":"builtin",".noaltmacro":"builtin",".nolist":"builtin",".octa":"builtin",".offset":"builtin",".org":"builtin",".p2align":"builtin",".popsection":"builtin",".previous":"builtin",".print":"builtin",".protected":"builtin",".psize":"builtin",".purgem":"builtin",".pushsection":"builtin",".quad":"builtin",".reloc":"builtin",".rept":"builtin",".sbttl":"builtin",".scl":"builtin",".section":"builtin",".set":"builtin",".short":"builtin",".single":"builtin",".size":"builtin",".skip":"builtin",".sleb128":"builtin",".space":"builtin",".stab":"builtin",".string":"builtin",".struct":"builtin",".subsection":"builtin",".symver":"builtin",".tag":"builtin",".text":"builtin",".title":"builtin",".type":"builtin",".uleb128":"builtin",".val":"builtin",".version":"builtin",".vtable_entry":"builtin",".vtable_inherit":"builtin",".warning":"builtin",".weak":"builtin",".weakref":"builtin",".word":"builtin"},t={};function n(i,l){for(var e,a=!1;null!=(e=i.next());){if("/"===e&&a){l.tokenize=null;break}a="*"===e}return"comment"}return"x86"===i?(e="#",t.al="variable",t.ah="variable",t.ax="variable",t.eax="variableName.special",t.rax="variableName.special",t.bl="variable",t.bh="variable",t.bx="variable",t.ebx="variableName.special",t.rbx="variableName.special",t.cl="variable",t.ch="variable",t.cx="variable",t.ecx="variableName.special",t.rcx="variableName.special",t.dl="variable",t.dh="variable",t.dx="variable",t.edx="variableName.special",t.rdx="variableName.special",t.si="variable",t.esi="variableName.special",t.rsi="variableName.special",t.di="variable",t.edi="variableName.special",t.rdi="variableName.special",t.sp="variable",t.esp="variableName.special",t.rsp="variableName.special",t.bp="variable",t.ebp="variableName.special",t.rbp="variableName.special",t.ip="variable",t.eip="variableName.special",t.rip="variableName.special",t.cs="keyword",t.ds="keyword",t.ss="keyword",t.es="keyword",t.fs="keyword",t.gs="keyword"):"arm"!==i&&"armv6"!==i||(e="@",a.syntax="builtin",t.r0="variable",t.r1="variable",t.r2="variable",t.r3="variable",t.r4="variable",t.r5="variable",t.r6="variable",t.r7="variable",t.r8="variable",t.r9="variable",t.r10="variable",t.r11="variable",t.r12="variable",t.sp="variableName.special",t.lr="variableName.special",t.pc="variableName.special",t.r13=t.sp,t.r14=t.lr,t.r15=t.pc,l.push((function(i,l){if("#"===i)return l.eatWhile(/\w/),"number"}))),{name:"gas",startState:function(){return{tokenize:null}},token:function(i,b){if(b.tokenize)return b.tokenize(i,b);if(i.eatSpace())return null;var r,u,s=i.next();if("/"===s&&i.eat("*"))return b.tokenize=n,n(i,b);if(s===e)return i.skipToEnd(),"comment";if('"'===s)return function(i,l){for(var e,a=!1;null!=(e=i.next());){if('"'===e&&!a)return!1;a=!a&&"\\"===e}}(i),"string";if("."===s)return i.eatWhile(/\w/),u=i.current().toLowerCase(),(r=a[u])||null;if("="===s)return i.eatWhile(/\w/),"tag";if("{"===s)return"bracket";if("}"===s)return"bracket";if(/\d/.test(s))return"0"===s&&i.eat("x")?(i.eatWhile(/[0-9a-fA-F]/),"number"):(i.eatWhile(/\d/),"number");if(/\w/.test(s))return i.eatWhile(/\w/),i.eat(":")?"tag":(u=i.current().toLowerCase(),(r=t[u])||null);for(var c=0;ct,gasArm:()=>n});const t=a("x86"),n=a("arm")}}]);
+//# sourceMappingURL=5950.index.js.map
\ No newline at end of file
diff --git a/book/_build/html/_static/5950.index.js.map b/book/_build/html/_static/5950.index.js.map
new file mode 100644
index 0000000..62cfd81
--- /dev/null
+++ b/book/_build/html/_static/5950.index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"5950.index.js","mappings":"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","sources":["webpack://thebe/../../node_modules/@codemirror/legacy-modes/mode/gas.js"],"sourcesContent":["function mkGas(arch) {\n // If an architecture is specified, its initialization function may\n // populate this array with custom parsing functions which will be\n // tried in the event that the standard functions do not find a match.\n var custom = [];\n\n // The symbol used to start a line comment changes based on the target\n // architecture.\n // If no architecture is pased in \"parserConfig\" then only multiline\n // comments will have syntax support.\n var lineCommentStartSymbol = \"\";\n\n // These directives are architecture independent.\n // Machine specific directives should go in their respective\n // architecture initialization function.\n // Reference:\n // http://sourceware.org/binutils/docs/as/Pseudo-Ops.html#Pseudo-Ops\n var directives = {\n \".abort\" : \"builtin\",\n \".align\" : \"builtin\",\n \".altmacro\" : \"builtin\",\n \".ascii\" : \"builtin\",\n \".asciz\" : \"builtin\",\n \".balign\" : \"builtin\",\n \".balignw\" : \"builtin\",\n \".balignl\" : \"builtin\",\n \".bundle_align_mode\" : \"builtin\",\n \".bundle_lock\" : \"builtin\",\n \".bundle_unlock\" : \"builtin\",\n \".byte\" : \"builtin\",\n \".cfi_startproc\" : \"builtin\",\n \".comm\" : \"builtin\",\n \".data\" : \"builtin\",\n \".def\" : \"builtin\",\n \".desc\" : \"builtin\",\n \".dim\" : \"builtin\",\n \".double\" : \"builtin\",\n \".eject\" : \"builtin\",\n \".else\" : \"builtin\",\n \".elseif\" : \"builtin\",\n \".end\" : \"builtin\",\n \".endef\" : \"builtin\",\n \".endfunc\" : \"builtin\",\n \".endif\" : \"builtin\",\n \".equ\" : \"builtin\",\n \".equiv\" : \"builtin\",\n \".eqv\" : \"builtin\",\n \".err\" : \"builtin\",\n \".error\" : \"builtin\",\n \".exitm\" : \"builtin\",\n \".extern\" : \"builtin\",\n \".fail\" : \"builtin\",\n \".file\" : \"builtin\",\n \".fill\" : \"builtin\",\n \".float\" : \"builtin\",\n \".func\" : \"builtin\",\n \".global\" : \"builtin\",\n \".gnu_attribute\" : \"builtin\",\n \".hidden\" : \"builtin\",\n \".hword\" : \"builtin\",\n \".ident\" : \"builtin\",\n \".if\" : \"builtin\",\n \".incbin\" : \"builtin\",\n \".include\" : \"builtin\",\n \".int\" : \"builtin\",\n \".internal\" : \"builtin\",\n \".irp\" : \"builtin\",\n \".irpc\" : \"builtin\",\n \".lcomm\" : \"builtin\",\n \".lflags\" : \"builtin\",\n \".line\" : \"builtin\",\n \".linkonce\" : \"builtin\",\n \".list\" : \"builtin\",\n \".ln\" : \"builtin\",\n \".loc\" : \"builtin\",\n \".loc_mark_labels\" : \"builtin\",\n \".local\" : \"builtin\",\n \".long\" : \"builtin\",\n \".macro\" : \"builtin\",\n \".mri\" : \"builtin\",\n \".noaltmacro\" : \"builtin\",\n \".nolist\" : \"builtin\",\n \".octa\" : \"builtin\",\n \".offset\" : \"builtin\",\n \".org\" : \"builtin\",\n \".p2align\" : \"builtin\",\n \".popsection\" : \"builtin\",\n \".previous\" : \"builtin\",\n \".print\" : \"builtin\",\n \".protected\" : \"builtin\",\n \".psize\" : \"builtin\",\n \".purgem\" : \"builtin\",\n \".pushsection\" : \"builtin\",\n \".quad\" : \"builtin\",\n \".reloc\" : \"builtin\",\n \".rept\" : \"builtin\",\n \".sbttl\" : \"builtin\",\n \".scl\" : \"builtin\",\n \".section\" : \"builtin\",\n \".set\" : \"builtin\",\n \".short\" : \"builtin\",\n \".single\" : \"builtin\",\n \".size\" : \"builtin\",\n \".skip\" : \"builtin\",\n \".sleb128\" : \"builtin\",\n \".space\" : \"builtin\",\n \".stab\" : \"builtin\",\n \".string\" : \"builtin\",\n \".struct\" : \"builtin\",\n \".subsection\" : \"builtin\",\n \".symver\" : \"builtin\",\n \".tag\" : \"builtin\",\n \".text\" : \"builtin\",\n \".title\" : \"builtin\",\n \".type\" : \"builtin\",\n \".uleb128\" : \"builtin\",\n \".val\" : \"builtin\",\n \".version\" : \"builtin\",\n \".vtable_entry\" : \"builtin\",\n \".vtable_inherit\" : \"builtin\",\n \".warning\" : \"builtin\",\n \".weak\" : \"builtin\",\n \".weakref\" : \"builtin\",\n \".word\" : \"builtin\"\n };\n\n var registers = {};\n\n function x86() {\n lineCommentStartSymbol = \"#\";\n\n registers.al = \"variable\";\n registers.ah = \"variable\";\n registers.ax = \"variable\";\n registers.eax = \"variableName.special\";\n registers.rax = \"variableName.special\";\n\n registers.bl = \"variable\";\n registers.bh = \"variable\";\n registers.bx = \"variable\";\n registers.ebx = \"variableName.special\";\n registers.rbx = \"variableName.special\";\n\n registers.cl = \"variable\";\n registers.ch = \"variable\";\n registers.cx = \"variable\";\n registers.ecx = \"variableName.special\";\n registers.rcx = \"variableName.special\";\n\n registers.dl = \"variable\";\n registers.dh = \"variable\";\n registers.dx = \"variable\";\n registers.edx = \"variableName.special\";\n registers.rdx = \"variableName.special\";\n\n registers.si = \"variable\";\n registers.esi = \"variableName.special\";\n registers.rsi = \"variableName.special\";\n\n registers.di = \"variable\";\n registers.edi = \"variableName.special\";\n registers.rdi = \"variableName.special\";\n\n registers.sp = \"variable\";\n registers.esp = \"variableName.special\";\n registers.rsp = \"variableName.special\";\n\n registers.bp = \"variable\";\n registers.ebp = \"variableName.special\";\n registers.rbp = \"variableName.special\";\n\n registers.ip = \"variable\";\n registers.eip = \"variableName.special\";\n registers.rip = \"variableName.special\";\n\n registers.cs = \"keyword\";\n registers.ds = \"keyword\";\n registers.ss = \"keyword\";\n registers.es = \"keyword\";\n registers.fs = \"keyword\";\n registers.gs = \"keyword\";\n }\n\n function armv6() {\n // Reference:\n // http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001l/QRC0001_UAL.pdf\n // http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf\n lineCommentStartSymbol = \"@\";\n directives.syntax = \"builtin\";\n\n registers.r0 = \"variable\";\n registers.r1 = \"variable\";\n registers.r2 = \"variable\";\n registers.r3 = \"variable\";\n registers.r4 = \"variable\";\n registers.r5 = \"variable\";\n registers.r6 = \"variable\";\n registers.r7 = \"variable\";\n registers.r8 = \"variable\";\n registers.r9 = \"variable\";\n registers.r10 = \"variable\";\n registers.r11 = \"variable\";\n registers.r12 = \"variable\";\n\n registers.sp = \"variableName.special\";\n registers.lr = \"variableName.special\";\n registers.pc = \"variableName.special\";\n registers.r13 = registers.sp;\n registers.r14 = registers.lr;\n registers.r15 = registers.pc;\n\n custom.push(function(ch, stream) {\n if (ch === '#') {\n stream.eatWhile(/\\w/);\n return \"number\";\n }\n });\n }\n\n if (arch === \"x86\") {\n x86();\n } else if (arch === \"arm\" || arch === \"armv6\") {\n armv6();\n }\n\n function nextUntilUnescaped(stream, end) {\n var escaped = false, next;\n while ((next = stream.next()) != null) {\n if (next === end && !escaped) {\n return false;\n }\n escaped = !escaped && next === \"\\\\\";\n }\n return escaped;\n }\n\n function clikeComment(stream, state) {\n var maybeEnd = false, ch;\n while ((ch = stream.next()) != null) {\n if (ch === \"/\" && maybeEnd) {\n state.tokenize = null;\n break;\n }\n maybeEnd = (ch === \"*\");\n }\n return \"comment\";\n }\n\n return {\n name: \"gas\",\n startState: function() {\n return {\n tokenize: null\n };\n },\n\n token: function(stream, state) {\n if (state.tokenize) {\n return state.tokenize(stream, state);\n }\n\n if (stream.eatSpace()) {\n return null;\n }\n\n var style, cur, ch = stream.next();\n\n if (ch === \"/\") {\n if (stream.eat(\"*\")) {\n state.tokenize = clikeComment;\n return clikeComment(stream, state);\n }\n }\n\n if (ch === lineCommentStartSymbol) {\n stream.skipToEnd();\n return \"comment\";\n }\n\n if (ch === '\"') {\n nextUntilUnescaped(stream, '\"');\n return \"string\";\n }\n\n if (ch === '.') {\n stream.eatWhile(/\\w/);\n cur = stream.current().toLowerCase();\n style = directives[cur];\n return style || null;\n }\n\n if (ch === '=') {\n stream.eatWhile(/\\w/);\n return \"tag\";\n }\n\n if (ch === '{') {\n return \"bracket\";\n }\n\n if (ch === '}') {\n return \"bracket\";\n }\n\n if (/\\d/.test(ch)) {\n if (ch === \"0\" && stream.eat(\"x\")) {\n stream.eatWhile(/[0-9a-fA-F]/);\n return \"number\";\n }\n stream.eatWhile(/\\d/);\n return \"number\";\n }\n\n if (/\\w/.test(ch)) {\n stream.eatWhile(/\\w/);\n if (stream.eat(\":\")) {\n return 'tag';\n }\n cur = stream.current().toLowerCase();\n style = registers[cur];\n return style || null;\n }\n\n for (var i = 0; i < custom.length; i++) {\n style = custom[i](ch, stream, state);\n if (style) {\n return style;\n }\n }\n },\n\n languageData: {\n commentTokens: {\n line: lineCommentStartSymbol,\n block: {open: \"/*\", close: \"*/\"}\n }\n }\n };\n};\n\nexport const gas = mkGas(\"x86\")\nexport const gasArm = mkGas(\"arm\")\n"],"names":["mkGas","arch","custom","lineCommentStartSymbol","directives","registers","clikeComment","stream","state","ch","maybeEnd","next","tokenize","al","ah","ax","eax","rax","bl","bh","bx","ebx","rbx","cl","cx","ecx","rcx","dl","dh","dx","edx","rdx","si","esi","rsi","di","edi","rdi","sp","esp","rsp","bp","ebp","rbp","ip","eip","rip","cs","ds","ss","es","fs","gs","syntax","r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","lr","pc","r13","r14","r15","push","eatWhile","name","startState","token","eatSpace","style","cur","eat","skipToEnd","end","escaped","nextUntilUnescaped","current","toLowerCase","test","i","length","languageData","commentTokens","line","block","open","close","gas","gasArm"],"sourceRoot":""}
\ No newline at end of file
diff --git a/book/_build/html/_static/5983.index.js b/book/_build/html/_static/5983.index.js
new file mode 100644
index 0000000..5c9ba28
--- /dev/null
+++ b/book/_build/html/_static/5983.index.js
@@ -0,0 +1,2 @@
+"use strict";(self.webpackChunkthebe=self.webpackChunkthebe||[]).push([[5983],{55983:(O,Q,$)=>{$.r(Q),$.d(Q,{autoCloseTags:()=>A,completionPath:()=>u,esLint:()=>N,javascript:()=>J,javascriptLanguage:()=>h,jsxLanguage:()=>G,localCompletionSource:()=>v,scopeCompletionSource:()=>j,snippets:()=>m,tsxLanguage:()=>R,typescriptLanguage:()=>q,typescriptSnippets:()=>b});var i=$(51392),e=$(86253);const a=[9,10,11,12,13,32,133,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8232,8233,8239,8287,12288],Z=new i.IK({start:!1,shift:(O,Q)=>3==Q||4==Q||307==Q?O:308==Q,strict:!1}),S=new i.Jq(((O,Q)=>{let{next:$}=O;(125==$||-1==$||Q.context)&&O.acceptToken(305)}),{contextual:!0,fallback:!0}),r=new i.Jq(((O,Q)=>{let $,{next:i}=O;a.indexOf(i)>-1||(47!=i||47!=($=O.peek(1))&&42!=$)&&(125==i||59==i||-1==i||Q.context||O.acceptToken(304))}),{contextual:!0}),t=new i.Jq(((O,Q)=>{let{next:$}=O;if((43==$||45==$)&&(O.advance(),$==O.next)){O.advance();let $=!Q.context&&Q.canShift(1);O.acceptToken($?1:2)}}),{contextual:!0}),o=(0,e.Gv)({"get set async static":e.pJ.modifier,"for while do if else switch try catch finally return throw break continue default case":e.pJ.controlKeyword,"in of await yield void typeof delete instanceof":e.pJ.operatorKeyword,"let var const using function class extends":e.pJ.definitionKeyword,"import export from":e.pJ.moduleKeyword,"with debugger as new":e.pJ.keyword,TemplateString:e.pJ.special(e.pJ.string),super:e.pJ.atom,BooleanLiteral:e.pJ.bool,this:e.pJ.self,null:e.pJ.null,Star:e.pJ.modifier,VariableName:e.pJ.variableName,"CallExpression/VariableName TaggedTemplateExpression/VariableName":e.pJ.function(e.pJ.variableName),VariableDefinition:e.pJ.definition(e.pJ.variableName),Label:e.pJ.labelName,PropertyName:e.pJ.propertyName,PrivatePropertyName:e.pJ.special(e.pJ.propertyName),"CallExpression/MemberExpression/PropertyName":e.pJ.function(e.pJ.propertyName),"FunctionDeclaration/VariableDefinition":e.pJ.function(e.pJ.definition(e.pJ.variableName)),"ClassDeclaration/VariableDefinition":e.pJ.definition(e.pJ.className),PropertyDefinition:e.pJ.definition(e.pJ.propertyName),PrivatePropertyDefinition:e.pJ.definition(e.pJ.special(e.pJ.propertyName)),UpdateOp:e.pJ.updateOperator,"LineComment Hashbang":e.pJ.lineComment,BlockComment:e.pJ.blockComment,Number:e.pJ.number,String:e.pJ.string,Escape:e.pJ.escape,ArithOp:e.pJ.arithmeticOperator,LogicOp:e.pJ.logicOperator,BitOp:e.pJ.bitwiseOperator,CompareOp:e.pJ.compareOperator,RegExp:e.pJ.regexp,Equals:e.pJ.definitionOperator,Arrow:e.pJ.function(e.pJ.punctuation),": Spread":e.pJ.punctuation,"( )":e.pJ.paren,"[ ]":e.pJ.squareBracket,"{ }":e.pJ.brace,"InterpolationStart InterpolationEnd":e.pJ.special(e.pJ.brace),".":e.pJ.derefOperator,", ;":e.pJ.separator,"@":e.pJ.meta,TypeName:e.pJ.typeName,TypeDefinition:e.pJ.definition(e.pJ.typeName),"type enum interface implements namespace module declare":e.pJ.definitionKeyword,"abstract global Privacy readonly override":e.pJ.modifier,"is keyof unique infer":e.pJ.operatorKeyword,JSXAttributeValue:e.pJ.attributeValue,JSXText:e.pJ.content,"JSXStartTag JSXStartCloseTag JSXSelfCloseEndTag JSXEndTag":e.pJ.angleBracket,"JSXIdentifier JSXNameSpacedName":e.pJ.tagName,"JSXAttribute/JSXIdentifier JSXAttribute/JSXNameSpacedName":e.pJ.attributeName,"JSXBuiltin/JSXIdentifier":e.pJ.standard(e.pJ.tagName)}),n={__proto__:null,export:16,as:21,from:29,default:32,async:37,function:38,extends:48,this:52,true:60,false:60,null:72,void:76,typeof:80,super:98,new:132,delete:148,yield:157,await:161,class:166,public:223,private:223,protected:223,readonly:225,instanceof:244,satisfies:247,in:248,const:250,import:282,keyof:337,unique:341,infer:347,is:383,abstract:403,implements:405,type:407,let:410,var:412,using:415,interface:421,enum:425,namespace:431,module:433,declare:437,global:441,for:460,of:469,while:472,with:476,do:480,if:484,else:486,switch:490,case:496,try:502,catch:506,finally:510,return:514,throw:518,break:522,continue:526,debugger:530},l={__proto__:null,async:119,get:121,set:123,declare:183,public:185,private:185,protected:185,static:187,abstract:189,override:191,readonly:197,accessor:199,new:387},p={__proto__:null,"<":139},P=i.WQ.deserialize({version:14,states:"$6zO%TQUOOO%[QUOOO'_QWOOP(lOSOOO*zQ(CjO'#CgO+ROpO'#ChO+aO!bO'#ChO+oO07`O'#D[O.QQUO'#DbO.bQUO'#DmO%[QUO'#DwO0fQUO'#EPOOQ(CY'#EX'#EXO1PQSO'#EUOOQO'#Ej'#EjOOQO'#Id'#IdO1XQSO'#GlO1dQSO'#EiO1iQSO'#EiO3kQ(CjO'#JeO6[Q(CjO'#JfO6xQSO'#FXO6}Q#tO'#FpOOQ(CY'#Fa'#FaO7YO&jO'#FaO7hQ,UO'#FwO9OQSO'#FvOOQ(CY'#Jf'#JfOOQ(CW'#Je'#JeO9TQSO'#GpOOQQ'#KQ'#KQO9`QSO'#IQO9eQ(C[O'#IROOQQ'#JR'#JROOQQ'#IV'#IVQ`QUOOO`QUOOO%[QUO'#DoO9mQUO'#D{O9tQUO'#D}O9ZQSO'#GlO9{Q,UO'#CmO:ZQSO'#EhO:fQSO'#EsO:kQ,UO'#F`O;YQSO'#GlOOQO'#KR'#KRO;_QSO'#KRO;mQSO'#GtO;mQSO'#GuO;mQSO'#GwO9ZQSO'#GzO]QSO'#HZO>eQSO'#HaO>eQSO'#HcO`QUO'#HeO>eQSO'#HgO>eQSO'#HjO>jQSO'#HpO>oQ(C]O'#HvO%[QUO'#HxO>zQ(C]O'#HzO?VQ(C]O'#H|O9eQ(C[O'#IOO?bQ(CjO'#CgO@dQWO'#DgQOQSOOO%[QUO'#D}O@zQSO'#EQO9{Q,UO'#EhOAVQSO'#EhOAbQ`O'#F`OOQQ'#Ce'#CeOOQ(CW'#Dl'#DlOOQ(CW'#Ji'#JiO%[QUO'#JiOOQO'#Jm'#JmOOQO'#Ia'#IaOBbQWO'#EaOOQ(CW'#E`'#E`OC^Q(C`O'#EaOChQWO'#ETOOQO'#Jl'#JlOC|QWO'#JmOEZQWO'#ETOChQWO'#EaPEhO?MpO'#C`POOO)CDp)CDpOOOO'#IW'#IWOEsOpO,59SOOQ(CY,59S,59SOOOO'#IX'#IXOFRO!bO,59SO%[QUO'#D^OOOO'#IZ'#IZOFaO07`O,59vOOQ(CY,59v,59vOFoQUO'#I[OGSQSO'#JgOIUQbO'#JgO+}QUO'#JgOI]QSO,59|OIsQSO'#EjOJQQSO'#JuOJ]QSO'#JtOJ]QSO'#JtOJeQSO,5;WOJjQSO'#JsOOQ(CY,5:X,5:XOJqQUO,5:XOLrQ(CjO,5:cOMcQSO,5:kOM|Q(C[O'#JrONTQSO'#JqO9TQSO'#JqONiQSO'#JqONqQSO,5;VONvQSO'#JqO!#OQbO'#JfOOQ(CY'#Cg'#CgO%[QUO'#EPO!#nQ`O,5:pOOQO'#Jn'#JnOOQO-ElOOQQ'#JZ'#JZOOQQ,5>m,5>mOOQQ-ExQ(CjO,5:iOOQO,5@m,5@mO!?iQ,UO,5=WO!?wQ(C[O'#J[O9OQSO'#J[O!@YQ(C[O,59XO!@eQWO,59XO!@mQ,UO,59XO9{Q,UO,59XO!@xQSO,5;TO!AQQSO'#HYO!AfQSO'#KVO%[QUO,5;xO!7cQWO,5;zO!AnQSO,5=sO!AsQSO,5=sO!AxQSO,5=sO9eQ(C[O,5=sO;mQSO,5=cOOQO'#Cs'#CsO!BWQWO,5=`O!B`Q,UO,5=aO!BkQSO,5=cO!BpQ`O,5=fO!BxQSO'#KRO>jQSO'#HPO9ZQSO'#HRO!B}QSO'#HRO9{Q,UO'#HTO!CSQSO'#HTOOQQ,5=i,5=iO!CXQSO'#HUO!CjQSO'#CmO!CoQSO,58}O!CyQSO,58}O!FOQUO,58}OOQQ,58},58}O!F`Q(C[O,58}O%[QUO,58}O!HkQUO'#H]OOQQ'#H^'#H^OOQQ'#H_'#H_O`QUO,5=uO!IRQSO,5=uO`QUO,5={O`QUO,5=}O!IWQSO,5>PO`QUO,5>RO!I]QSO,5>UO!IbQUO,5>[OOQQ,5>b,5>bO%[QUO,5>bO9eQ(C[O,5>dOOQQ,5>f,5>fO!MlQSO,5>fOOQQ,5>h,5>hO!MlQSO,5>hOOQQ,5>j,5>jO!MqQWO'#DYO%[QUO'#JiO!N`QWO'#JiO!N}QWO'#DhO# `QWO'#DhO##qQUO'#DhO##xQSO'#JhO#$QQSO,5:RO#$VQSO'#EnO#$eQSO'#JvO#$mQSO,5;XO#$rQWO'#DhO#%PQWO'#ESOOQ(CY,5:l,5:lO%[QUO,5:lO#%WQSO,5:lO>jQSO,5;SO!@eQWO,5;SO!@mQ,UO,5;SO9{Q,UO,5;SO#%`QSO,5@TO#%eQ!LQO,5:pOOQO-E<_-E<_O#&kQ(C`O,5:{OChQWO,5:oO#&uQWO,5:oOChQWO,5:{O!@YQ(C[O,5:oOOQ(CW'#Ed'#EdOOQO,5:{,5:{O%[QUO,5:{O#'SQ(C[O,5:{O#'_Q(C[O,5:{O!@eQWO,5:oOOQO,5;R,5;RO#'mQ(C[O,5:{POOO'#IU'#IUP#(RO?MpO,58zPOOO,58z,58zOOOO-EvO+}QUO,5>vOOQO,5>|,5>|O#(mQUO'#I[OOQO-EWQ(CjO1G0yO#>_Q(CjO1G0yO#@VQ(CjO1G0yO#CVQ$IUO'#CgO#ETQ$IUO1G1[O#E[Q$IUO'#JfO!,YQSO1G1bO#ElQ(CjO,5?SOOQ(CW-EeQSO1G3kO$.fQUO1G3mO$2jQUO'#HlOOQQ1G3p1G3pO$2wQSO'#HrO>jQSO'#HtOOQQ1G3v1G3vO$3PQUO1G3vO9eQ(C[O1G3|OOQQ1G4O1G4OOOQ(CW'#GX'#GXO9eQ(C[O1G4QO9eQ(C[O1G4SO$7WQSO,5@TO!*SQUO,5;YO9TQSO,5;YO>jQSO,5:SO!*SQUO,5:SO!@eQWO,5:SO$7]Q$IUO,5:SOOQO,5;Y,5;YO$7gQWO'#I]O$7}QSO,5@SOOQ(CY1G/m1G/mO$8VQWO'#IcO$8aQSO,5@bOOQ(CW1G0s1G0sO# `QWO,5:SOOQO'#I`'#I`O$8iQWO,5:nOOQ(CY,5:n,5:nO#%ZQSO1G0WOOQ(CY1G0W1G0WO%[QUO1G0WOOQ(CY1G0n1G0nO>jQSO1G0nO!@eQWO1G0nO!@mQ,UO1G0nOOQ(CW1G5o1G5oO!@YQ(C[O1G0ZOOQO1G0g1G0gO%[QUO1G0gO$8pQ(C[O1G0gO$8{Q(C[O1G0gO!@eQWO1G0ZOChQWO1G0ZO$9ZQ(C[O1G0gOOQO1G0Z1G0ZO$9oQ(CjO1G0gPOOO-EvO$:]QSO1G5mO$:eQSO1G5zO$:mQbO1G5{O9TQSO,5>|O$:wQ(CjO1G5xO%[QUO1G5xO$;XQ(C[O1G5xO$;jQSO1G5wO$;jQSO1G5wO9TQSO1G5wO$;rQSO,5?PO9TQSO,5?POOQO,5?P,5?PO$WOOQQ,5>W,5>WO%[QUO'#HmO%(vQSO'#HoOOQQ,5>^,5>^O9TQSO,5>^OOQQ,5>`,5>`OOQQ7+)b7+)bOOQQ7+)h7+)hOOQQ7+)l7+)lOOQQ7+)n7+)nO%({QWO1G5oO%)aQ$IUO1G0tO%)kQSO1G0tOOQO1G/n1G/nO%)vQ$IUO1G/nO>jQSO1G/nO!*SQUO'#DhOOQO,5>w,5>wOOQO-E},5>}OOQO-EjQSO7+&YO!@eQWO7+&YOOQO7+%u7+%uO$9oQ(CjO7+&ROOQO7+&R7+&RO%[QUO7+&RO%*QQ(C[O7+&RO!@YQ(C[O7+%uO!@eQWO7+%uO%*]Q(C[O7+&RO%*kQ(CjO7++dO%[QUO7++dO%*{QSO7++cO%*{QSO7++cOOQO1G4k1G4kO9TQSO1G4kO%+TQSO1G4kOOQO7+%z7+%zO#%ZQSO<xOOQO-E<[-E<[O%2yQbO,5>yO%[QUO,5>yOOQO-E<]-E<]O%3TQSO1G5qOOQ(CY<tQ$IUO1G0yO%>{Q$IUO1G0yO%@sQ$IUO1G0yO%AWQ(CjO<XOOQQ,5>Z,5>ZO& PQSO1G3xO9TQSO7+&`O!*SQUO7+&`OOQO7+%Y7+%YO& UQ$IUO1G5{O>jQSO7+%YOOQ(CY<jQSO<jQSO7+)dO&6mQSO<{AN>{O%[QUOAN?XOOQO<